👋 Друзья, привет!
Хочу поделиться небольшой, но полезной наработкой для тех, кто работает с Telegram-ботами и отправкой изображений.
Ситуация:
У вас есть backend, на котором лежат изображения. Вы пытаетесь отправить их в чат бота с помощью
❌ Bad Request: wrong type of the web page content
Такое часто бывает, если:
* домен нестандартный (например, через туннель или локальный IP)
* сертификат Telegram не устраивает
* или просто он не может скачать файл напрямую.
🎯 Решение — скачать изображение вручную и отправить его как байты:
🛡 Это работает стабильно и безопасно. Независимо от особенностей хостинга или домена, Telegram получит реальный файл и всё отправится без ошибок.
Надеюсь, пригодится!
Хочу поделиться небольшой, но полезной наработкой для тех, кто работает с Telegram-ботами и отправкой изображений.
Ситуация:
У вас есть backend, на котором лежат изображения. Вы пытаетесь отправить их в чат бота с помощью
bot.send_photo, передавая прямую ссылку (image_url) — но Telegram отвечает чем-то вроде:❌ Bad Request: wrong type of the web page content
Такое часто бывает, если:
* домен нестандартный (например, через туннель или локальный IP)
* сертификат Telegram не устраивает
* или просто он не может скачать файл напрямую.
🎯 Решение — скачать изображение вручную и отправить его как байты:
import aiohttp
from aiogram.types import BufferedInputFile
async def send_photo_from_url(chat_id, image_url, caption=None, parse_mode="HTML"):
async with aiohttp.ClientSession() as session:
async with session.get(image_url) as resp:
if resp.status != 200:
raise Exception(f"Image load failed: {resp.status}")
img_bytes = await resp.read()
image = BufferedInputFile(img_bytes, filename="image.jpg")
await bot.send_photo(
chat_id=chat_id,
photo=image,
caption=caption,
parse_mode=parse_mode,
)
🛡 Это работает стабильно и безопасно. Независимо от особенностей хостинга или домена, Telegram получит реальный файл и всё отправится без ошибок.
Надеюсь, пригодится!
👍36🔥23❤7❤🔥1💘1
💭 А что, если пойти дальше?
Вместо того чтобы вручную возиться с кодом, почему бы не создать полноценный веб-интерфейс для отправки отложенных сообщений в Telegram — с поддержкой:
✨ форматированного текста
📸 изображений
📎 файлов
🔒 авторизации
🕒 планирования по времени
Всё это — через удобную, современную админку. Никаких команд в терминале — всё в пару кликов.
⚙️ Хочу рассказать, как реализовать такую систему на базе FastAPI, Aiogram 3 и SQLAlchemy, с гибкой очередью сообщений и полной готовностью к продакшену. Авторизацию можно будет снова сделать через Keycloak.
Будете ждать такую статью?
Вместо того чтобы вручную возиться с кодом, почему бы не создать полноценный веб-интерфейс для отправки отложенных сообщений в Telegram — с поддержкой:
✨ форматированного текста
📸 изображений
📎 файлов
🔒 авторизации
🕒 планирования по времени
Всё это — через удобную, современную админку. Никаких команд в терминале — всё в пару кликов.
⚙️ Хочу рассказать, как реализовать такую систему на базе FastAPI, Aiogram 3 и SQLAlchemy, с гибкой очередью сообщений и полной готовностью к продакшену. Авторизацию можно будет снова сделать через Keycloak.
Будете ждать такую статью?
2🔥124👍37❤11🤩3🤪3👎1🎄1
Генерация SSH-ключа на VPS и привязка к GitHub — быстро и просто 🚀
Чтобы работать с GitHub с VPS удобно и безопасно, без постоянного ввода логина и пароля, рекомендую настроить SSH-доступ. Это просто:
1️⃣ Создаём SSH-ключ (рекомендуется Ed25519):
Откройте терминал на сервере и выполните:
2️⃣ Используем стандартный путь (\~/.ssh/id\_ed25519):
Нажмите Enter при запросе пути. При желании задайте пароль — или оставьте пустым для удобства.
3️⃣ Копируем публичный ключ:
4️⃣ Добавляем ключ в GitHub:
GitHub → Settings → SSH and GPG keys → New SSH key
Вставьте ключ, дайте название (например,
5️⃣ Проверяем подключение:
Если увидите сообщение вроде “Hi username! You've successfully authenticated” — всё работает ✅
Теперь можно клонировать репозитории по SSH:
Важно! Убедитесь, что ссылки на репозитории в ваших проектах тоже используют SSH, а не HTTPS. Это можно проверить и изменить так:
🔄 Проверить текущую ссылку:
🔧 Изменить на SSH-ссылку:
Теперь вы готовы работать с репозиториями без лишней головной боли — быстро, безопасно и без постоянного ввода логина/пароля 💻🔐
Чтобы работать с GitHub с VPS удобно и безопасно, без постоянного ввода логина и пароля, рекомендую настроить SSH-доступ. Это просто:
1️⃣ Создаём SSH-ключ (рекомендуется Ed25519):
Откройте терминал на сервере и выполните:
ssh-keygen -t ed25519 -C "ваш_email@example.com"
2️⃣ Используем стандартный путь (\~/.ssh/id\_ed25519):
Нажмите Enter при запросе пути. При желании задайте пароль — или оставьте пустым для удобства.
3️⃣ Копируем публичный ключ:
cat ~/.ssh/id_ed25519.pub
4️⃣ Добавляем ключ в GitHub:
GitHub → Settings → SSH and GPG keys → New SSH key
Вставьте ключ, дайте название (например,
My VPS) и сохраните.5️⃣ Проверяем подключение:
ssh -T git@github.com
Если увидите сообщение вроде “Hi username! You've successfully authenticated” — всё работает ✅
Теперь можно клонировать репозитории по SSH:
git clone git@github.com:username/repository.git
Важно! Убедитесь, что ссылки на репозитории в ваших проектах тоже используют SSH, а не HTTPS. Это можно проверить и изменить так:
🔄 Проверить текущую ссылку:
git remote -v
🔧 Изменить на SSH-ссылку:
git remote set-url origin git@github.com:username/repository.git
Теперь вы готовы работать с репозиториями без лишней головной боли — быстро, безопасно и без постоянного ввода логина/пароля 💻🔐
👍25🔥9❤5🎉1
Полное руководство по настройке CI/CD для проектов на VueJS3 и FastAPI
Я подготовил небольшую, но ёмкую инструкцию по работе с технологией GitHub Actions. Если кратко, эта технология позволяет при пуше в репозиторий на GitHub автоматически запускать процессы, которые обновляют ваше приложение на VPS-сервере.
В руководстве я описал два простых примера: один - с использованием systemd для FastAPI, другой - с чистым Nginx для VueJS3. При этом GitHub Actions отлично подходит и для более сложных связок, например, с Docker.
Старался писать максимально доступно и без лишней «воды», так что заходите, кому интересно!
Полная инструкция доступна по ссылке: yakvenalex.ru/ru/all_technology/ci-cd-guide
Я подготовил небольшую, но ёмкую инструкцию по работе с технологией GitHub Actions. Если кратко, эта технология позволяет при пуше в репозиторий на GitHub автоматически запускать процессы, которые обновляют ваше приложение на VPS-сервере.
В руководстве я описал два простых примера: один - с использованием systemd для FastAPI, другой - с чистым Nginx для VueJS3. При этом GitHub Actions отлично подходит и для более сложных связок, например, с Docker.
Старался писать максимально доступно и без лишней «воды», так что заходите, кому интересно!
Полная инструкция доступна по ссылке: yakvenalex.ru/ru/all_technology/ci-cd-guide
🔥37👍12❤7⚡2🍾2🤪1
Простой способ скрывать автоматизацию браузера при работе с Playwright
Если вы используете Playwright для автоматизации браузера и хотите, чтобы сайты не определяли, что вы — бот, есть простой и эффективный трюк.
Шаг 1. Установка Playwright и драйверов
Шаг 2. Пример скрипта с обходом детекции автоматизации
Почему это работает?
- Аргумент
- Запуск браузера с этим параметром помогает скрыть автоматизацию от сайтов, которые пытаются определить ботов.
- Сайт intoli.com отлично подходит для проверки, видит ли сайт, что вы используете автоматизацию.
Этот простой приём помогает значительно снизить риск блокировок и детекций при автоматизации через Playwright. Попробуйте и убедитесь сами!
Если вы используете Playwright для автоматизации браузера и хотите, чтобы сайты не определяли, что вы — бот, есть простой и эффективный трюк.
Шаг 1. Установка Playwright и драйверов
pip install playwright==1.52.0 # или более новую версию
playwright install # установка всех драйверов
# или для конкретного браузера:
playwright install chromium # драйвер для Chrome/Chromium
Шаг 2. Пример скрипта с обходом детекции автоматизации
import asyncio
from playwright.async_api import async_playwright
async def main():
async with async_playwright() as p:
browser = await p.chromium.launch(
headless=False,
channel="chrome",
args=["--start-maximized", "--disable-blink-features=AutomationControlled"],
)
context = await browser.new_context(no_viewport=True)
page = await context.new_page()
await page.goto("https://intoli.com/blog/not-possible-to-block-chrome-headless/chrome-headless-test.html")
await page.wait_for_timeout(5000) # пауза 5 секунд для просмотра результата
await context.close()
if __name__ == "__main__":
asyncio.run(main())
Почему это работает?
- Аргумент
--disable-blink-features=AutomationControlled отключает встроенную в Chromium функцию, которая обычно выдаёт факт автоматизации (например, свойство navigator.webdriver).- Запуск браузера с этим параметром помогает скрыть автоматизацию от сайтов, которые пытаются определить ботов.
- Сайт intoli.com отлично подходит для проверки, видит ли сайт, что вы используете автоматизацию.
Этот простой приём помогает значительно снизить риск блокировок и детекций при автоматизации через Playwright. Попробуйте и убедитесь сами!
1❤26👍24🔥16🎄1🙉1
Легкий путь в Python
💭 А что, если пойти дальше? Вместо того чтобы вручную возиться с кодом, почему бы не создать полноценный веб-интерфейс для отправки отложенных сообщений в Telegram — с поддержкой: ✨ форматированного текста 📸 изображений 📎 файлов 🔒 авторизации 🕒 планирования…
Друзья, надеюсь соскучились. Скоро к вам вернусь. Надеюсь, что следующий месяц будет свободнее. На очереди, как и говорил, проект с веб-интерфейсом для телеграмм бота. Постараюсь к концу следующей недели выйти с новым материалом на Хабре.
🔥64❤15👍10❤🔥8👀2🤯1😱1
🧵 Бывает, нужна
В таких случаях на помощь приходит
Это отличный способ создать модель на лету, особенно когда нужно:
* собрать фильтр для DAO,
* подготовить временную обёртку под данные,
* протестировать какой-то кусок бизнес-логики без лишней бюрократии.
🛠 Ниже — 3 удобных способа использования
1. 📦 Обычное создание класса + отдельный вызов
✅ Подходит, если модель будет использоваться более одного раза
🧠 Имя
2. ⚡️ Создание и вызов — в одной строке, с именем
✅ Удобно, если модель используется один раз, но вы всё же хотите, чтобы она имела осмысленное имя (для дебага или логирования).
3. 🎭 Максимально лаконично — без имени
✅ Идеально для разовых задач, тестов, временных скриптов
⚠️ Но без имени будет сложнее отследить, если модель "взорвётся" в логах или ошибках.
💡 Напоминаю:
👨💻 Используйте этот приём, чтобы писать чище, быстрее и без лишнего шума в кодовой базе.
pydantic-модель… но лезть в schemas.py лень, да и незачемВ таких случаях на помощь приходит
create_model из Pydantic 🧙♂️Это отличный способ создать модель на лету, особенно когда нужно:
* собрать фильтр для DAO,
* подготовить временную обёртку под данные,
* протестировать какой-то кусок бизнес-логики без лишней бюрократии.
🛠 Ниже — 3 удобных способа использования
create_model1. 📦 Обычное создание класса + отдельный вызов
from pydantic import create_model
FilterModel = create_model('FilterModel', id=(int, ...))
filter_model = FilterModel(id=child_id)
✅ Подходит, если модель будет использоваться более одного раза
🧠 Имя
'FilterModel' здесь не просто строка — оно будет видно в логах, исключениях и IDE-подсказках, что может сильно облегчить отладку.2. ⚡️ Создание и вызов — в одной строке, с именем
from pydantic import create_model
filter_model = create_model('FilterModel', id=(int, ...))(id=child_id)
✅ Удобно, если модель используется один раз, но вы всё же хотите, чтобы она имела осмысленное имя (для дебага или логирования).
3. 🎭 Максимально лаконично — без имени
from pydantic import create_model
filter_model = create_model('', id=(int, ...))(id=child_id)
✅ Идеально для разовых задач, тестов, временных скриптов
⚠️ Но без имени будет сложнее отследить, если модель "взорвётся" в логах или ошибках.
💡 Напоминаю:
create_model создаёт полноценную BaseModel, так что она полностью совместима с остальной экосистемой Pydantic — включая .model_dump(), валидацию, .model_json(), .model_fields, и так далее.👨💻 Используйте этот приём, чтобы писать чище, быстрее и без лишнего шума в кодовой базе.
👍23❤5🔥4⚡2👎1🍌1🤝1🫡1
🔧 Git: "Не могу запушить!" - Простое решение конфликта веток
😱 Что случилось?
Вы сделали коммит, пытаетесь сделать
Причина: Пока вы работали, кто-то другой уже запушил свои изменения в эту же ветку.
🎯 Простое и безопасное решение
Шаг 1: Скачиваем новые изменения
✨ Если конфликтов НЕТ:
Git выведет что-то вроде:
Переходите сразу к Шагу 5! 🚀
Шаг 2: Если появились конфликты
Git покажет что-то вроде:
Шаг 3: Решаем конфликты (если они есть)
1. Открываем файл с конфликтом
2. Ищем строки с
3. Оставляем нужный код, удаляем служебные символы
4. Сохраняем файл
Шаг 4: Завершаем (только при конфликтах)
Шаг 5: Пушим результат
✅ Готово!
Ваши изменения теперь в репозитории поверх всех остальных.
🆘 Если запаниковали
💡 Главное: не паникуйте! Эта ошибка - норма в командной работе.
😱 Что случилось?
Вы сделали коммит, пытаетесь сделать
git push и получаете ошибку (вместо main имя ветки в которую вы пушили):! [rejected] main -> main (non-fast-forward)
Причина: Пока вы работали, кто-то другой уже запушил свои изменения в эту же ветку.
🎯 Простое и безопасное решение
Шаг 1: Скачиваем новые изменения
git pull --rebase origin main
Эта команда скачает чужие изменения и попытается поставить ваш коммит поверх них
✨ Если конфликтов НЕТ:
Git выведет что-то вроде:
Successfully rebased and updated refs/heads/main.
Успешно перемещён и обновлён refs/heads/main.
Переходите сразу к Шагу 5! 🚀
Шаг 2: Если появились конфликты
Git покажет что-то вроде:
CONFLICT (content): Merge conflict in file.py
Шаг 3: Решаем конфликты (если они есть)
1. Открываем файл с конфликтом
2. Ищем строки с
<<<<<<<, =======, >>>>>>>3. Оставляем нужный код, удаляем служебные символы
4. Сохраняем файл
Шаг 4: Завершаем (только при конфликтах)
git add .
git rebase --continue
Шаг 5: Пушим результат
git push origin main
✅ Готово!
Ваши изменения теперь в репозитории поверх всех остальных.
🆘 Если запаниковали
git rebase --abort
Вернет все как было до начала операции
💡 Главное: не паникуйте! Эта ошибка - норма в командной работе.
2🔥36👍14❤12⚡2😍2👏1🍌1
🚀 FastAPI app.state: правильное управление глобальным состоянием
app.state в FastAPI — это встроенный механизм для хранения данных, которые должны быть доступны на протяжении всего жизненного цикла приложения.
📝 Базовый синтаксис
🔧 Использование в зависимостях
⚡️ Преимущества app.state
✅ Типобезопасность — можно добавить типизацию через Pydantic
✅ Автоматическое управление — создание при старте, очистка при завершении
✅ Доступность везде — через Request object в любой части приложения
✅ Производительность — нет overhead на создание подключений в каждом запросе
💡 Лучшие практики
🔸 Используйте app.state для тяжелых ресурсов (пулы БД, ML модели, клиенты API)
🔸 Не храните пользовательские данные — только глобальные ресурсы
🔸 Всегда закрывайте ресурсы в блоке shutdown
🔸 Создавайте отдельные зависимости для каждого ресурса
Старый синтаксис с
app.state в FastAPI — это встроенный механизм для хранения данных, которые должны быть доступны на протяжении всего жизненного цикла приложения.
📝 Базовый синтаксис
from fastapi import FastAPI, Depends, Request
from contextlib import asynccontextmanager
# Современный синтаксис жизненного цикла (FastAPI 0.93+)
@asynccontextmanager
async def lifespan(app: FastAPI):
# Startup
app.state.database_pool = await create_db_pool()
app.state.redis_client = await create_redis_client()
app.state.ml_model = load_ml_model()
yield # Приложение работает
# Shutdown
await app.state.database_pool.close()
await app.state.redis_client.close()
app = FastAPI(lifespan=lifespan)
🔧 Использование в зависимостях
# Зависимость для получения данных из app.state
def get_db_pool(request: Request):
return request.app.state.database_pool
def get_redis(request: Request):
return request.app.state.redis_client
# Использование в эндпоинтах
@app.get("/users/{user_id}")
async def get_user(
user_id: int,
db_pool = Depends(get_db_pool),
redis = Depends(get_redis)
):
# Сначала проверяем кеш
cached = await redis.get(f"user:{user_id}")
if cached:
return json.loads(cached)
# Если нет в кеше, идем в БД
async with db_pool.acquire() as conn:
user = await conn.fetchrow("SELECT * FROM users WHERE id = $1", user_id)
await redis.setex(f"user:{user_id}", 300, json.dumps(dict(user)))
return user
⚡️ Преимущества app.state
✅ Типобезопасность — можно добавить типизацию через Pydantic
✅ Автоматическое управление — создание при старте, очистка при завершении
✅ Доступность везде — через Request object в любой части приложения
✅ Производительность — нет overhead на создание подключений в каждом запросе
💡 Лучшие практики
🔸 Используйте app.state для тяжелых ресурсов (пулы БД, ML модели, клиенты API)
🔸 Не храните пользовательские данные — только глобальные ресурсы
🔸 Всегда закрывайте ресурсы в блоке shutdown
🔸 Создавайте отдельные зависимости для каждого ресурса
Старый синтаксис с
@app.on_event("startup") устарел с версии 0.93. Используйте lifespan!👍29🔥10❤5❤🔥2⚡2💘2🦄2😁1
🧠💾 Если коротко, то я подключил нейронку напрямую к базе данных
Теперь вместо написания SQL запросов я просто говорю Claude человеческим языком:
💬 "Покажи всех сотрудников из отдела Engineering с их зарплатами"
💬 "Создай отчет по проектам с бюджетами"
💬 "Найди самых загруженных разработчиков"
А он сам формирует SQL, выполняет запрос и красиво выводит результат ✨
Рассказать вам как это работает? 🤔
Теперь вместо написания SQL запросов я просто говорю Claude человеческим языком:
💬 "Покажи всех сотрудников из отдела Engineering с их зарплатами"
💬 "Создай отчет по проектам с бюджетами"
💬 "Найди самых загруженных разработчиков"
А он сам формирует SQL, выполняет запрос и красиво выводит результат ✨
Рассказать вам как это работает? 🤔
🔥125👍38❤🔥5❤3👏3🤯2😱2🙈2🙊1
Легкий путь в Python
🧠💾 Если коротко, то я подключил нейронку напрямую к базе данных Теперь вместо написания SQL запросов я просто говорю Claude человеческим языком: 💬 "Покажи всех сотрудников из отдела Engineering с их зарплатами" 💬 "Создай отчет по проектам с бюджетами" 💬…
FastAPI + MCP + LLM как сервис — звучит как неплохая идея для статьи, не правда ли?
6🔥113👍34💯16🤩2🎄2
🚀 MCP + Локальная Llama: Файловая система под контролем ИИ
А вот ещё один пример интеграции MCP, но на этот раз уже с локальной нейросетью Meta-Llama-3.1-8B и MCP modelcontextprotocol/server-filesystem!
На скриншоте видно, как Llama успешно:
- 🤖 Понимает команду на русском языке
- 🔧 Выбирает правильный инструмент
- ✅ Создаёт файл
- 📁 Подтверждает выполнение операции
Что особенно круто:
- Никаких API-ключей — всё работает локально
- Llama понимает естественный язык и переводит в MCP-команды
- Полный контроль над файловой системой через стандартизированный протокол
Стек: Python + MCP + Ollama + @modelcontextprotocol/server-filesystem
Model Context Protocol действительно упрощает интеграцию ИИ с внешними инструментами. Один протокол — множество возможностей!
А вот ещё один пример интеграции MCP, но на этот раз уже с локальной нейросетью Meta-Llama-3.1-8B и MCP modelcontextprotocol/server-filesystem!
На скриншоте видно, как Llama успешно:
- 🤖 Понимает команду на русском языке
- 🔧 Выбирает правильный инструмент
fs_write_file- ✅ Создаёт файл
ex.py с HTTP-запросом к python.org- 📁 Подтверждает выполнение операции
Что особенно круто:
- Никаких API-ключей — всё работает локально
- Llama понимает естественный язык и переводит в MCP-команды
- Полный контроль над файловой системой через стандартизированный протокол
Стек: Python + MCP + Ollama + @modelcontextprotocol/server-filesystem
Model Context Protocol действительно упрощает интеграцию ИИ с внешними инструментами. Один протокол — множество возможностей!
🔥31👍16❤4☃1😇1🤪1
🚀 Создаем AI агента с доступом к файловой системе за 5 минут!
Недавно попробовал Model Context Protocol (MCP) от Anthropic с OpenAI — и это просто магия! Теперь GPT может работать с вашими файлами напрямую.
📦 Быстрая установка
💻 Минимальный код
✨ Что происходит под капотом?
В этом примере мы подключили к агенту MCP filesystem server, который дает GPT возможность:
- 📁 Читать и создавать файлы
- 📋 Просматривать содержимое папок
- 🔍 Искать файлы по содержимому
- ✏️ Редактировать код напрямую
🎯 Результат
Агент автоматически:
1. Создает файл
2. Пишет рабочий код для OpenAI API
3. Сохраняет его в файловую систему
Никакого копирования кода вручную — AI делает всё сам!
🔥 Возможности
- Автоматизация: Создание целых проектов одной командой
- Рефакторинг: "Отрефактори все .py файлы в папке"
- Документация: "Создай README для этого проекта"
- Тестирование: "Напиши тесты для всех модулей"
MCP — это будущее AI агентов. Теперь они не просто болтают, а реально работают с вашими данными! 🤖
Другие MCP сервера подключаются по такой-же логике.
P.S. Пока локальные модели с которыми я работал не позволили получить такого-же качественного профита от взаимодействия с MCP, но, возможно, вопрос в мощности железа и качестве самих локальных LLM.
Недавно попробовал Model Context Protocol (MCP) от Anthropic с OpenAI — и это просто магия! Теперь GPT может работать с вашими файлами напрямую.
📦 Быстрая установка
pip install openai-agents
💻 Минимальный код
import asyncio
from agents import Agent, Runner
from agents.mcp import MCPServerStdio
import os
os.environ["OPENAI_API_KEY"] = "sk-proj-..."
async def main():
async with MCPServerStdio(
params={
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "."],
}
) as mcp_server:
agent = Agent(
name="Assistant",
instructions="Ты ассистент, который может работать с файлами через инструменты.",
mcp_servers=[mcp_server]
)
result = await Runner.run(
agent,
"Создай файл test.py с примером get запроса к серверу openai"
)
print(result.final_output)
asyncio.run(main())
✨ Что происходит под капотом?
В этом примере мы подключили к агенту MCP filesystem server, который дает GPT возможность:
- 📁 Читать и создавать файлы
- 📋 Просматривать содержимое папок
- 🔍 Искать файлы по содержимому
- ✏️ Редактировать код напрямую
🎯 Результат
Агент автоматически:
1. Создает файл
test.py2. Пишет рабочий код для OpenAI API
3. Сохраняет его в файловую систему
Никакого копирования кода вручную — AI делает всё сам!
🔥 Возможности
- Автоматизация: Создание целых проектов одной командой
- Рефакторинг: "Отрефактори все .py файлы в папке"
- Документация: "Создай README для этого проекта"
- Тестирование: "Напиши тесты для всех модулей"
MCP — это будущее AI агентов. Теперь они не просто болтают, а реально работают с вашими данными! 🤖
Другие MCP сервера подключаются по такой-же логике.
P.S. Пока локальные модели с которыми я работал не позволили получить такого-же качественного профита от взаимодействия с MCP, но, возможно, вопрос в мощности железа и качестве самих локальных LLM.
🔥27❤10⚡2🎉1🏆1💋1
Интегрируем в OpenAI Agents локальные LLM
Вчера я показывал пример, как легко интегрировать облачный OpenAI в свои проекты в связке с библиотекой openai-agents. Но это далеко не единственная возможность, ведь там, буквально из коробки, присутствует интеграция с локальными LLM.
Первое что нужно сделать — это поднять локальную нейросеть, которая поддерживает интеграцию с MCP. Самый популярный вариант — это Llama через Ollama.
Подготовка локальной модели
1. Устанавливаем Ollama
2. Скачиваем модель llama3:8b
3. Проверяем, что все корректно работает
4. Запускаем Ollama в режиме сервера
Код интеграции
Ключевые отличия от облачного варианта
К основным отличиям от вчерашнего примера можно отнести блок, в котором мы описываем модель с которой нам предстоит работать:
Остальное идентично вчерашнему примеру.
Вчера я показывал пример, как легко интегрировать облачный OpenAI в свои проекты в связке с библиотекой openai-agents. Но это далеко не единственная возможность, ведь там, буквально из коробки, присутствует интеграция с локальными LLM.
Первое что нужно сделать — это поднять локальную нейросеть, которая поддерживает интеграцию с MCP. Самый популярный вариант — это Llama через Ollama.
Подготовка локальной модели
1. Устанавливаем Ollama
# Для Linux/macOS
curl -fsSL https://ollama.ai/install.sh | sh
# Для Windows
# Скачиваем и устанавливаем с официального сайта
2. Скачиваем модель llama3:8b
ollama pull llama3:8b
3. Проверяем, что все корректно работает
ollama run llama3:8b
4. Запускаем Ollama в режиме сервера
ollama serve
Код интеграции
import asyncio
from agents import Agent, Runner, OpenAIChatCompletionsModel
from agents.mcp import MCPServerStdio
from openai import AsyncOpenAI
async def main():
async with MCPServerStdio(
params={
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "."],
},
client_session_timeout_seconds=60
) as mcp_server:
agent = Agent(
name="FileAssistant",
instructions="Ты ассистент, который может работать с файлами через инструменты MCP.",
model=OpenAIChatCompletionsModel(
model="llama3:8b",
openai_client=AsyncOpenAI(
base_url="http://localhost:11434/v1",
api_key="ollama"
)
),
mcp_servers=[mcp_server]
)
result = await Runner.run(
agent,
"Создай файл example.py с примером GET запроса к OpenAI API"
)
print(result.final_output)
asyncio.run(main())
Ключевые отличия от облачного варианта
К основным отличиям от вчерашнего примера можно отнести блок, в котором мы описываем модель с которой нам предстоит работать:
model=OpenAIChatCompletionsModel(
model="llama3:8b", # Название модели в Ollama
openai_client=AsyncOpenAI(
base_url="http://localhost:11434/v1", # Локальный адрес Ollama
api_key="ollama" # Любая строка для совместимости
)
)
Остальное идентично вчерашнему примеру.
👍18🔥12❤8👏1🍓1🫡1
Как научить нейросеть работать с 1000 медицинскими книгами?
🧠💡 RAG (Retrieval-Augmented Generation) — ваш идеальный инструмент!
🔹 Проблема
У вас есть 1000 книг по медицине (учебники, исследования, клинические рекомендации). Как сделать так, чтобы нейросеть:
✅ Отвечала точно (без выдумок).
✅ Ссылалась на источники.
✅ Не требовала перетренировки при добавлении новых книг.
Решение — связка векторной БД + LLM!
🔹 Шаг 1. Подготовка данных
1. Разбиваем книги на чанки (например, по 1–2 страницы):
2. Добавляем метаданные для каждого чанка:
- Название книги, автор, год, страница.
- Теги (
🔹 Шаг 2. Векторизация и база данных
1. Преобразуем текст в вектора (эмбеддинги):
2. Загружаем в векторную БД (например, Qdrant или Milvus):
Почему векторная БД?
- Ищет по смыслу, а не ключевым словам.
- Поддерживает фильтры (например, только статьи после 2020 года).
🔹 Шаг 3. Поиск и генерация ответов
1. Векторизуем запрос пользователя:
> *«Какие современные методы лечения гипертонии у пожилых?»*
2. Ищем релевантные чанки:
3. Передаем контекст в LLM:
4. Получаем ответ с ссылками:
> *«Согласно "Руководству по кардиологии" (2023), для пожилых рекомендованы ... [стр. 78].»*
🔹 Оптимизации
- Гибридный поиск: Комбинируйте векторный поиск с ключевыми словами.
- Ранжирование: Добавьте перекрестный энкодер для уточнения топ-3 чанков.
- Кэширование: Сохраняйте результаты частых запросов.
🔹 Готовые решения
- LlamaIndex — для быстрого RAG-пайплайна.
- Haystack — если нужны готовые компоненты.
- LangChain — для гибкой настройки.
💡 Итог:
1. Чанки + вектора — превращаем книги в «поисковый индекс».
2. LLM + контекст — отвечает точно и без галлюцинаций.
3. Ссылки на источники — прозрачность и доверие.
Примеры запросов:
- *«Какие противопоказания у препарата X?»*
- *«Алгоритм диагностики инфаркта по последним гайдлайнам»*
Попробуйте на своих данных! Если нужно углубиться в детали — спрашивайте. 🚀
🧠💡 RAG (Retrieval-Augmented Generation) — ваш идеальный инструмент!
🔹 Проблема
У вас есть 1000 книг по медицине (учебники, исследования, клинические рекомендации). Как сделать так, чтобы нейросеть:
✅ Отвечала точно (без выдумок).
✅ Ссылалась на источники.
✅ Не требовала перетренировки при добавлении новых книг.
Решение — связка векторной БД + LLM!
🔹 Шаг 1. Подготовка данных
1. Разбиваем книги на чанки (например, по 1–2 страницы):
from langchain.text_splitter import RecursiveCharacterTextSplitter
splitter = RecursiveCharacterTextSplitter(
chunk_size=1000, # ~500-1000 токенов
chunk_overlap=100 # Перекрытие для контекста
)
chunks = splitter.split_text(book_text)
2. Добавляем метаданные для каждого чанка:
- Название книги, автор, год, страница.
- Теги (
кардиология, фармакология, диагностика). 🔹 Шаг 2. Векторизация и база данных
1. Преобразуем текст в вектора (эмбеддинги):
from sentence_transformers import SentenceTransformer
model = SentenceTransformer("paraphrase-multilingual-MiniLM-L12-v2") # Поддержка русского
vector = model.encode("Текст о лечении гипертонии...")
2. Загружаем в векторную БД (например, Qdrant или Milvus):
import qdrant_client
client = qdrant_client.QdrantClient("localhost")
client.upsert(
collection_name="medical_books",
points=[
{"id": 1, "vector": vector.tolist(), "payload": {"title": "Кардиология", "page": 45}}
]
)
Почему векторная БД?
- Ищет по смыслу, а не ключевым словам.
- Поддерживает фильтры (например, только статьи после 2020 года).
🔹 Шаг 3. Поиск и генерация ответов
1. Векторизуем запрос пользователя:
> *«Какие современные методы лечения гипертонии у пожилых?»*
2. Ищем релевантные чанки:
results = client.search(
collection_name="medical_books",
query_vector=model.encode("Современные методы лечения гипертонии").tolist(),
limit=5 # Топ-5 самых полезных фрагментов
)
3. Передаем контекст в LLM:
prompt = f"""
Ты — медицинский эксперт. Ответь на вопрос, используя ТОЛЬКО данные ниже.
Если информации нет, скажи «Не нашел данных».
Вопрос: {user_question}
Контекст:
{chunk1_text} [Источник: {chunk1_title}, стр. {chunk1_page}]
{chunk2_text} [Источник: {chunk2_title}, стр. {chunk2_page}]
"""
4. Получаем ответ с ссылками:
> *«Согласно "Руководству по кардиологии" (2023), для пожилых рекомендованы ... [стр. 78].»*
🔹 Оптимизации
- Гибридный поиск: Комбинируйте векторный поиск с ключевыми словами.
- Ранжирование: Добавьте перекрестный энкодер для уточнения топ-3 чанков.
- Кэширование: Сохраняйте результаты частых запросов.
🔹 Готовые решения
- LlamaIndex — для быстрого RAG-пайплайна.
- Haystack — если нужны готовые компоненты.
- LangChain — для гибкой настройки.
💡 Итог:
1. Чанки + вектора — превращаем книги в «поисковый индекс».
2. LLM + контекст — отвечает точно и без галлюцинаций.
3. Ссылки на источники — прозрачность и доверие.
Примеры запросов:
- *«Какие противопоказания у препарата X?»*
- *«Алгоритм диагностики инфаркта по последним гайдлайнам»*
Попробуйте на своих данных! Если нужно углубиться в детали — спрашивайте. 🚀
🔥44❤14👍10🤝3🙏1🤡1🍾1
🔌 Что такое MCP простыми словами
Представьте: у вас есть компьютер (векторная база данных) и флешка (нейросеть). Чтобы они работали вместе, нужен USB-разъем — это и есть MCP (Model Context Protocol).
🖥 Компьютер хранит кучу файлов и документов
💾 Флешка умеет их обрабатывать и анализировать
🔌 USB-разъем позволяет им "общаться" друг с другом
Без MCP: нейросеть работает сама по себе, не зная о ваших данных
С MCP: нейросеть может:
- Читать ваши документы
- Анализировать базы данных
- Работать с внешними сервисами
- Использовать актуальную информацию
Это как если бы ваша флешка вдруг получила доступ ко всем файлам компьютера и могла с ними работать в реальном времени!
MCP делает AI-помощников по-настоящему полезными — они перестают быть просто болтунами и становятся инструментами, которые знают контекст вашей работы.
Представьте: у вас есть компьютер (векторная база данных) и флешка (нейросеть). Чтобы они работали вместе, нужен USB-разъем — это и есть MCP (Model Context Protocol).
🖥 Компьютер хранит кучу файлов и документов
💾 Флешка умеет их обрабатывать и анализировать
🔌 USB-разъем позволяет им "общаться" друг с другом
Без MCP: нейросеть работает сама по себе, не зная о ваших данных
С MCP: нейросеть может:
- Читать ваши документы
- Анализировать базы данных
- Работать с внешними сервисами
- Использовать актуальную информацию
Это как если бы ваша флешка вдруг получила доступ ко всем файлам компьютера и могла с ними работать в реальном времени!
MCP делает AI-помощников по-настоящему полезными — они перестают быть просто болтунами и становятся инструментами, которые знают контекст вашей работы.
👍24🔥14❤8🤔3🤝3😍1🙉1👾1
🤖 Скоро на Хабре: Создаём настоящего ИИ-агента за час!
Надоели чат-боты, которые только разговаривают? Пора создать настоящего ИИ-помощника, который умеет:
• 📁 Читать и анализировать файлы
• 🔍 Искать информацию в интернете
• 🧠 Запоминать контекст разговора
• ⚡️ Работать асинхронно и стабильно
Что будет в статье:
✅ Два готовых агента: классификатор вакансий + файловый помощник
✅ Поддержка Ollama, OpenAI, DeepSeek — любая модель на выбор
✅ Промышленная архитектура: логирование, retry, обработка ошибок
✅ Полная интеграция в Python без no-code конструкторов
✅ LangGraph + MCP — современный стек для ИИ-агентов
🎯 От настройки до рабочего агента за 60 минут
Материал готов, проходит финальную вычитку. Публикация — завтра-послезавтра!
📂 Пока ждёте — изучайте исходники: GitHub
В репозитории примеры от простых до продвинутых. В статье будет и практика, и теория — идеально для тех, кто хочет разобраться с MCP серверами и ИИ-агентами.
Будете ждать выхода статьи?
Надоели чат-боты, которые только разговаривают? Пора создать настоящего ИИ-помощника, который умеет:
• 📁 Читать и анализировать файлы
• 🔍 Искать информацию в интернете
• 🧠 Запоминать контекст разговора
• ⚡️ Работать асинхронно и стабильно
Что будет в статье:
✅ Два готовых агента: классификатор вакансий + файловый помощник
✅ Поддержка Ollama, OpenAI, DeepSeek — любая модель на выбор
✅ Промышленная архитектура: логирование, retry, обработка ошибок
✅ Полная интеграция в Python без no-code конструкторов
✅ LangGraph + MCP — современный стек для ИИ-агентов
🎯 От настройки до рабочего агента за 60 минут
Материал готов, проходит финальную вычитку. Публикация — завтра-послезавтра!
📂 Пока ждёте — изучайте исходники: GitHub
В репозитории примеры от простых до продвинутых. В статье будет и практика, и теория — идеально для тех, кто хочет разобраться с MCP серверами и ИИ-агентами.
Будете ждать выхода статьи?
4🔥98👍21❤7🍾2🤝2👌1😍1🐳1
📚 Базовое знакомство с разработкой ИИ-агентов
Опубликовал на Хабре статью по созданию ИИ-агентов с использованием LangGraph и LangChain. Это первое знакомство с темой — в планах, если увижу интерес от аудитории и вашу поддержку, полноценный мини-курс по разработке агентов на этом стеке.
🔍 О чем статья:
• Объясняю концепцию ИИ-агентов с нуля
• Разбираю что такое MCP и зачем он нужен разработчикам
• Показываю архитектуру решения на LangGraph в связке с LangChain
• Два практических кейса: классификация вакансий и работа с файлами
• Промышленная архитектура с логированием и обработкой ошибок
⚙️ Технический стек:
LangGraph + LangChain + MCP с поддержкой разных моделей (Ollama, OpenAI, DeepSeek)
Материал, как обычно, старался подать максимально доступно — все будет понятно даже тем, кто вообще не в теме. Идеально для старта в мире MCP-серверов и ИИ-агентов.
📖 Статья: Как научить нейросеть работать руками: создание полноценного ИИ-агента с MCP и LangGraph
💻 Исходный код: GitHub
Опубликовал на Хабре статью по созданию ИИ-агентов с использованием LangGraph и LangChain. Это первое знакомство с темой — в планах, если увижу интерес от аудитории и вашу поддержку, полноценный мини-курс по разработке агентов на этом стеке.
🔍 О чем статья:
• Объясняю концепцию ИИ-агентов с нуля
• Разбираю что такое MCP и зачем он нужен разработчикам
• Показываю архитектуру решения на LangGraph в связке с LangChain
• Два практических кейса: классификация вакансий и работа с файлами
• Промышленная архитектура с логированием и обработкой ошибок
⚙️ Технический стек:
LangGraph + LangChain + MCP с поддержкой разных моделей (Ollama, OpenAI, DeepSeek)
Материал, как обычно, старался подать максимально доступно — все будет понятно даже тем, кто вообще не в теме. Идеально для старта в мире MCP-серверов и ИИ-агентов.
📖 Статья: Как научить нейросеть работать руками: создание полноценного ИИ-агента с MCP и LangGraph
💻 Исходный код: GitHub
Хабр
Как научить нейросеть работать руками: создание полноценного ИИ-агента с MCP и LangGraph за час
Друзья, приветствую! Надеюсь, успели соскучиться. Последние пару месяцев я с головой ушёл в исследование интеграции ИИ-агентов в собственные Python-проекты. В процессе накопилось немало практических...
21🔥67👍23❤5🫡2👌1😍1🤝1
🔧 Пример простого графа на LangGraph с визуализацией
LangGraph — мощный инструмент для построения графов вычислений, особенно полезен в агентных системах и workflow-автоматизации. Ниже — минимальный пример, где создаётся граф, выполняющий математические операции (сумму или произведение) над списком чисел.
📌 Что делает этот граф:
* Принимает список чисел и операцию (
* Выполняет нужную операцию
* Возвращает результат
* И сохраняет визуализацию графа в
🖼 После запуска — в папке появится файл
LangGraph — мощный инструмент для построения графов вычислений, особенно полезен в агентных системах и workflow-автоматизации. Ниже — минимальный пример, где создаётся граф, выполняющий математические операции (сумму или произведение) над списком чисел.
📌 Что делает этот граф:
* Принимает список чисел и операцию (
+ или *)* Выполняет нужную операцию
* Возвращает результат
* И сохраняет визуализацию графа в
graph.pngfrom typing import Dict, TypedDict
from langgraph.graph import StateGraph
# Определение состояния
class AgentState(TypedDict):
numbers: list[int]
operation: str
result: int
# Узел обработки
def process_node(state: AgentState) -> AgentState:
operation = state["operation"]
numbers = state["numbers"]
if operation == "*":
rez_value = 1
for i in numbers:
rez_value *= i
elif operation == "+":
rez_value = sum(numbers)
else:
rez_value = 0
state["result"] = rez_value
return state
# Создание графа
graph = StateGraph(AgentState)
graph.add_node("process", process_node)
graph.set_entry_point("process")
graph.set_finish_point("process")
app = graph.compile()
# Визуализация графа
with open("graph.png", "wb") as f:
f.write(app.get_graph().draw_mermaid_png())
# Запуск графа
result = app.invoke({"numbers": [1, 2, 3, 10], "operation": "+"})
print(result["result"]) # 👉 16
🖼 После запуска — в папке появится файл
graph.png с визуализацией графа (приложил к посту полученное изображение).👍14🔥14🤝3🤔1🙏1🤗1