Привет! Меня зовут Фаина, я системный аналитик с опытом более 5 лет. В последнее время все чаще стала задумываться как системному аналитику в текущих реалиях применять в работе ИИ. Так началось мое погружение в увлекательный мир LangChain, ИИ, RAG и векторные БД.
Для начального исследования я решила попробовать что-то достаточно простое и базовое. Так в мою голову пришла идея создать ТГ бота, который напоминает о запланированных делах
Первая версия была максимально простой: просто скрипт, который парсил текст грубыми регулярками. Фразу «встреча с X в 19:45» он ещё понимал, а вот «позвонить X через 2 часа» — уже нет.
Тут я вспомнила про LangChain. Честно признаюсь, до этого проекта я только краем уха слышала про этот фреймворк. Он предоставляет отличную возможность для сборки AI-приложений.
Я перепробовала кучу вариантов:
Попытка №1: OpenAI (ChatGPT)
Самый очевидный выбор. Быстро получила ключ, написала код, запустила... и получила ошибку unsupported_country_region_territory. OpenAI не дружит с моим регионом. Можно было бы попробовать настроить VPN/прокси, но слишком сильно заморачиваться для первого проекта не хотелось.
Попытка №2: DeepSeek
Китайский конкурент. Действительно, работает быстро, цены смешные, регион не проверяет. Но после пары тестов на моём аккаунте закончился баланс (Insufficient Balance), а пополнять в тот момент не хотелось.
Попытка №3: GigaChat от Сбера
Российская модель, которая сразу заработала. Никаких блокировок, отличный русский язык, понятная документация. Мой бот наконец-то заработал и начал понимать мои запросы, но бесплатные токены быстро закончились.
Попытка №4 (финальная): Gemma 3 27B
Тут я задумалась: «А что, если не зависеть ни от каких API?» И тут я вспомнила про Ollama и локальные модели.
Выбор пал на Gemma 3 27B от Google. Модель весит прилично (около 17 ГБ), но теперь есть возможность локального запуска. Никаких API-ключей, никаких ограничений, никакого интернета — только ты и твой ноут.
По итогу получился следующий тех стек:
Python 3.10
python-telegram-bot==13.15
langchain-ollama
Ollama
После нескольких итераций и кучи исправлений родился универсальный помощник, который понимает:
встреча с X завтра в 15:00
сдать отчет через 2 часа
купить хлеб вечером
Он сам определяет тип напоминания, сам вычисляет время (даже если я пишу «послезавтра» или «через 3 часа»), сам запоминает и присылает уведомление ровно за минуту до события.
Первым делом создаем виртуальное окружение (это спасёт от конфликтов зависимостей):
python -m venv langchain_env source langchain_env/bin/activate # для Linux/Mac # или для Windows: langchain_env\Scripts\activate
Устанавливаем зависимости:
pip install langchain-ollama python-telegram-bot==13.15 python-dotenv
Подключение локальной Gemma 3 через Ollama:
from langchain_ollama import ChatOllama llm = ChatOllama( model="gemma3:27b", # название модели temperature=0, # чем ниже, тем точнее num_predict=1024, # макс. длина ответа keep_alive="10m", # держать в памяти 10 минут )
Важно: перед запуском убедитесь, что Ollama сервер работает:
ollama serve ollama pull gemma3:27b
Необходимо настроить промт так, чтобы модель гарантированно возвращала чистый JSON:
from langchain_core.prompts import ChatPromptTemplate from langchain_core.output_parsers import StrOutputParser reminder_prompt = ChatPromptTemplate.from_messages([ ("system", """Ты - помощник, который извлекает информацию о напоминаниях из текста. Текущее время: {current_time} Проанализируй сообщение и верни ТОЛЬКО JSON с полями: - type: тип (meeting/call/task/shopping/health/birthday/other) - title: название (обязательно) - datetime: когда напомнить (формат ГГГГ-ММ-ДД ЧЧ:ММ) Примеры: "встреча с Х завтра в 15:00" -> {{"type": "meeting", "title": "Встреча с Х", "datetime": "2024-01-16 15:00"}} "позвонить Х через 2 часа" -> {{"type": "call", "title": "Позвонить Х", "datetime": "2024-01-15 18:30"}} Верни ТОЛЬКО JSON, без пояснений."""), ("human", "{text}") ]) chain = reminder_prompt | llm | StrOutputParser()
Обратите внимание на двойные фигурные скобки {{ — это экранирование в LangChain, чтобы шаблон правильно обработал примеры JSON.
Модель иногда возвращает JSON внутри markdown-блоков, поэтому нужна очистка:
def parse_reminder_request(text): try: result = chain.invoke({ "text": text, "current_time": datetime.now().strftime("%H:%M %d.%m.%Y") }) # Очищаем от markdown result = result.strip() if '```json' in result: result = result.split('```json')[1].split('```')[0].strip() elif '```' in result: result = result.split('```')[1].split('```')[0].strip() data = json.loads(result) print(f"🔍 Распознано: {data}") return data except Exception as e: print(f"❌ Ошибка: {e}") return None
Самая простая и надёжная реализация — без APScheduler, на обычном threading:
import threading import time from datetime import datetime import telegram def check_reminders(): bot = telegram.Bot(token=TELEGRAM_TOKEN) while True: try: now = datetime.now() for reminder in reminders: if not reminder.get('notified') and now >= reminder['datetime']: bot.send_message( chat_id=CHAT_ID, text=f"🔔 **НАПОМИНАНИЕ!**\n\n{reminder['text']}" ) reminder['notified'] = True save_reminders() time.sleep(5) # проверяем каждые 5 секунд except Exception as e: print(f"❌ Ошибка: {e}") time.sleep(5) # Запускаем в отдельном потоке reminder_thread = threading.Thread(target=check_reminders, daemon=True) reminder_thread.start()
Базовые команды и обработка сообщений:
from telegram.ext import Updater, CommandHandler, MessageHandler, Filters def start(update, context): update.message.reply_text( "👋 Привет! Просто напиши мне:\n" ) def handle_message(update, context): text = update.message.text print(f"📨 Получено: {text}") reminder, response = add_reminder_from_text(text) update.message.reply_text(response) def main(): updater = Updater(TELEGRAM_TOKEN, use_context=True) dp = updater.dispatcher dp.add_handler(CommandHandler("start", start)) dp.add_handler(CommandHandler("list", list_reminders)) dp.add_handler(CommandHandler("today", today_reminders)) dp.add_handler(MessageHandler(Filters.text, handle_message)) updater.start_polling() updater.idle()
C:\Users\mfrus\meeting_reminder_bot\ ├── langchain_env\ # виртуальное окружение ├── .env # TELEGRAM_TOKEN и CHAT_ID ├── simple_universal_bot.py # главный бот ├── gemma3_bot.py # резервная копия ├── reminders.json # база напоминаний └── requirements.txt # зависимости
TELEGRAM_BOT_TOKEN=ваш_токен YOUR_CHAT_ID=ваш_id
langchain-ollama>=0.1.0 python-telegram-bot==13.15 python-dotenv>=1.0.0
# 1. Активировать окружение langchain_env\Scripts\activate # 2. Убедиться, что Ollama запущен ollama list # должна быть gemma3:27b # 3. Запустить бота python simple_universal_bot.py
Сейчас у меня есть:
✅ Полностью локальный Telegram-бот
✅ Работает на моём компьютере 24/7
✅ Понимает естественный язык благодаря Gemma 3
✅ Не требует API-ключей
✅ Напоминает о чём угодно: от встреч до покупки хлеба
Весь код доступен на GitHub. Буду рада вопросам и предложениям в комментариях!
Источник


