AI-бот со streaming
Бот который пересылает сообщения в LLM (OpenAI/llama.cpp/локальный) и стримит ответ обратно.
Ключевые приёмы
- sendChatAction "typing" — индикатор «бот печатает»
- editMessageText — обновляем сообщение по мере прихода chunks из LLM
Пример (Python + aiogram + OpenAI)
import asyncio, os
from openai import AsyncOpenAI
from aiogram import Bot, Dispatcher, F
from aiogram.client.session.aiohttp import AiohttpSession
from aiogram.client.telegram import TelegramAPIServer
from aiogram.types import Message
from aiogram.filters import CommandStart
session = AiohttpSession(api=TelegramAPIServer.from_base('https://api.telefon.chat'))
bot = Bot(token=os.environ['BOT_TOKEN'], session=session)
dp = Dispatcher()
ai = AsyncOpenAI(api_key=os.environ['OPENAI_API_KEY'])
@dp.message(CommandStart())
async def start(m: Message):
await m.answer('Привет! Спрашивай что угодно.')
@dp.message(F.text)
async def chat(m: Message):
# Показываем «печатает...»
await bot.send_chat_action(m.chat.id, 'typing')
# Создаём пустое сообщение, потом будем редактировать
placeholder = await m.answer('⏳ Думаю...')
# Стрим из OpenAI
accumulated = ''
last_edit = 0
response = await ai.chat.completions.create(
model='gpt-4',
messages=[{'role': 'user', 'content': m.text}],
stream=True
)
async for chunk in response:
delta = chunk.choices[0].delta.content or ''
accumulated += delta
# Редактируем не чаще 1 раза в секунду чтобы не упереться в rate limit
now = asyncio.get_event_loop().time()
if now - last_edit > 1.2:
try:
await bot.edit_message_text(
chat_id=m.chat.id,
message_id=placeholder.message_id,
text=accumulated + ' ▍'
)
last_edit = now
except Exception:
pass
# Финальное обновление без курсора
await bot.edit_message_text(
chat_id=m.chat.id,
message_id=placeholder.message_id,
text=accumulated
)
if __name__ == '__main__':
asyncio.run(dp.start_polling(bot))
Боевой пример
karfly/chatgpt_telegram_bot — github.com/karfly/chatgpt_telegram_bot. ~7k★. Поддержка диалогов, голосового ввода (whisper), генерации картинок (DALL-E), персон (assistant/coder/translator).
Совет
Для генерации с локальной моделью используйте OpenAI-совместимый endpoint типа llama.cpp /v1/chat/completions — код API клиента не меняется.