19 декабря 2024 г. Go Telegram Gemini Ai Aws Lambda Bot
В этой статье мы рассмотрим, как создать интеллектуального Telegram бота на Go, который выступает в роли прокси между пользователями и API Google Gemini. Бот будет выполнять две основные функции: отвечать на сообщения пользователей и генерировать изображения. Хотя этот механизм может быть существенно расширен дополнительными возможностями, такими как генерация голоса и видео, мы сосредоточимся на этих двух типах запросов для простоты.
Бот использует интеллектуальный механизм маршрутизации, где первый запрос к AI действует как роутер для определения типа запроса пользователя. AI инструктируется либо вернуть обычный ответ в виде диалога, либо структурированный вывод, который может быть передан специализированной модели для генерации изображений.
graph TD
A[Сообщение пользователя] --> B[Обработчик Telegram бота]
B --> C[Запрос к роутеру AI]
C --> D{Тип запроса?}
D -->|Текстовый ответ| E[Gemini Chat API]
D -->|Генерация изображения| F[Gemini Image Generation API]
E --> G[Отправить текст пользователю]
F --> H[Отправить изображение пользователю]
Начнём с настройки базовой структуры проекта:
package main
import (
"bytes"
"context"
"encoding/json"
"fmt"
"os"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/s3"
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
"google.golang.org/api/option"
"google.golang.org/api/generativeai"
)
Сначала нам нужно настроить бота с API ключами:
type Config struct {
TelegramToken string
GeminiAPIKey string
}
func loadConfig() *Config {
return &Config{
TelegramToken: os.Getenv("TELEGRAM_TOKEN"),
GeminiAPIKey: os.Getenv("GEMINI_API_KEY"),
}
}
Роутер использует Gemini для анализа сообщения пользователя и определения соответствующего действия:
type RequestType string
const (
RequestTypeText RequestType = "text"
RequestTypeImage RequestType = "image"
)
type RouterResponse struct {
Type RequestType `json:"type"`
Prompt string `json:"prompt,omitempty"`
Message string `json:"message,omitempty"`
}
Промпт роутера должен быть лаконичным и понятным:
Вы роутер запросов для Telegram бота. Анализируйте сообщения пользователей и отвечайте JSON:
- Если пользователь хочет сгенерировать изображение, верните: {"type":"image","prompt":"описание"}
- В противном случае верните: {"type":"text","message":"ваш ответ"}
Вот реализация роутера:
func routeRequest(ctx context.Context, client *generativeai.Client,
userMsg string) RouterResponse {
model := client.GenerativeModel("gemini-3-pro-preview")
model.SystemInstruction = "Маршрутизируйте запросы: возвращайте JSON с типом и prompt/message"
resp, _ := model.GenerateContent(ctx, userMsg)
var routerResp RouterResponse
json.Unmarshal([]byte(resp.Text), &routerResp)
return routerResp
}
Вот как мы обрабатываем входящие сообщения Telegram:
func handleMessage(ctx context.Context, bot *tgbotapi.BotAPI,
client *generativeai.Client, update tgbotapi.Update) {
userMsg := update.Message.Text
routerResp := routeRequest(ctx, client, userMsg)
switch routerResp.Type {
case RequestTypeImage:
generateAndSendImage(ctx, bot, client, update, routerResp.Prompt)
case RequestTypeText:
sendTextResponse(bot, update, routerResp.Message)
}
}
Для обычных текстовых ответов мы используем chat API Gemini:
func sendTextResponse(bot *tgbotapi.BotAPI,
update tgbotapi.Update, message string) {
msg := tgbotapi.NewMessage(update.Message.Chat.ID, message)
msg.ReplyToMessageID = update.Message.MessageID
bot.Send(msg)
}
Для генерации изображений мы вызываем endpoint генерации изображений Gemini:
func generateAndSendImage(ctx context.Context, bot *tgbotapi.BotAPI,
client *generativeai.Client,
update tgbotapi.Update, prompt string) {
model := client.GenerativeModel("gemini-2.5-flash-image")
resp, err := model.GenerateContent(ctx, prompt)
if err != nil {
sendTextResponse(bot, update, "Ошибка генерации изображения")
return
}
photo := tgbotapi.NewPhoto(update.Message.Chat.ID,
tgbotapi.FileBytes{
Name: "image.png",
Bytes: resp.ImageData,
})
bot.Send(photo)
}
Функция main настраивает бота и начинает прослушивание:
func main() {
cfg := loadConfig()
bot, _ := tgbotapi.NewBotAPI(cfg.TelegramToken)
client, _ := generativeai.NewClient(context.Background(),
option.WithAPIKey(cfg.GeminiAPIKey))
u := tgbotapi.NewUpdate(0)
updates := bot.GetUpdatesChan(u)
for update := range updates {
if update.Message != nil {
go handleMessage(context.Background(), bot, client, update)
}
}
}
Вот лаконичные системные промпты для различных сценариев:
Промпт роутера:
Маршрутизируйте запросы пользователей: возвращайте JSON с "type":"image" и "prompt" для запросов изображений,
или "type":"text" с "message" для разговоров.
Промпт ассистента для чата:
Вы полезный ассистент. Предоставляйте ясные, лаконичные ответы на вопросы пользователей.
Шаблон промпта для генерации изображений:
Сгенерируйте высококачественное изображение на основе: {user_prompt}
Эта архитектура может быть легко расширена для поддержки дополнительных возможностей:
RequestTypeVoice и используйте text-to-speech APIRequestTypeVideo и интегрируйте сервисы генерации видеоПаттерн роутера позволяет добавлять новые типы запросов без изменения основной логики обработки сообщений.
Для того чтобы бот понимал контекст и поддерживал связные диалоги, ему необходим доступ к истории сообщений. Поскольку Lambda функции не имеют состояния, нам нужно внешнее хранилище для истории разговоров. AWS S3 отлично подходит для этой цели, так как он легко интегрируется с Lambda и предоставляет надёжное, масштабируемое хранилище.
AI модели, такие как Gemini, работают значительно лучше, когда у них есть доступ к контексту разговора. Без истории каждое сообщение обрабатывается независимо, что делает невозможным для бота:
Мы можем хранить каждый разговор как JSON файл в S3, используя ID чата в качестве ключа. Этот подход позволяет нам:
Вот как реализовать хранение разговоров:
func saveConversation(ctx context.Context, s3Client *s3.Client,
chatID int64, messages []Message) error {
key := fmt.Sprintf("conversations/%d.json", chatID)
data, _ := json.Marshal(messages)
_, err := s3Client.PutObject(ctx, &s3.PutObjectInput{
Bucket: aws.String("bot-conversations"),
Key: aws.String(key),
Body: bytes.NewReader(data),
})
return err
}
Загрузка истории разговора:
func loadConversation(ctx context.Context, s3Client *s3.Client,
chatID int64) ([]Message, error) {
key := fmt.Sprintf("conversations/%d.json", chatID)
resp, err := s3Client.GetObject(ctx, &s3.GetObjectInput{
Bucket: aws.String("bot-conversations"),
Key: aws.String(key),
})
if err != nil {
return []Message{}, nil // Вернуть пустой, если не найдено
}
defer resp.Body.Close()
var messages []Message
json.NewDecoder(resp.Body).Decode(&messages)
return messages, nil
}
При обработке сообщения загрузите историю, добавьте новое сообщение, отправьте полный контекст в Gemini и сохраните обновлённый разговор обратно в S3. Это обеспечивает поддержку контекста ботом в нескольких взаимодействиях, используя при этом stateless архитектуру Lambda.
Деплой этого бота как AWS Lambda функции предоставляет несколько значительных преимуществ по сравнению с традиционными серверными решениями. Давайте разберём, почему Lambda особенно хорошо подходит для Telegram ботов:
1. Экономическая эффективность
2. Автоматическое масштабирование
3. Нулевое управление инфраструктурой
4. Высокая доступность и надёжность
5. Идеальное соответствие архитектуре webhook
6. Преимущества разработки и деплоя
Для Telegram бота с переменными паттернами трафика, которому не нужна постоянная доступность, Lambda обеспечивает оптимальный баланс стоимости, производительности и операционной простоты.
Детальные инструкции по настройке AWS CLI, созданию Lambda функции, настройке Function URL и автоматизации деплоя вынесены в отдельную статью: Деплой Telegram бота на AWS Lambda с Function URL.
В этой статье вы найдёте:
Эта архитектура предоставляет гибкую основу для создания AI-телеграм ботов. Паттерн роутера позволяет легко расширять функциональность для новых возможностей, сохраняя при этом поддерживаемость кодовой базы. Деплой на AWS Lambda обеспечивает масштабируемость и экономическую эффективность для использования в продакшене.
Эта статья является продолжением статьи “Создание AI-телеграм бота на Go с Gemini API и AWS Lambda” и содержит детальные инструкции по настройке и деплою Telegram бота на AWS Lambda с использованием Function URL.
Read More → Go Telegram Aws Lambda Deploy Function-Url Cli