from typing import List, Dict, Optional from gemini_model import GeminiModel class RouteDescriber: """ Класс для работы с описанием маршрутов и ответами на вопросы пользователей через GeminiModel. """ def __init__(self): self.model = GeminiModel() self.conversation_history = [] self.route_points = [] self.route_description = "" self.parser_chat_context = "" def _call_model(self, prompt: str, system_instruction: Optional[str] = None) -> str: """ Вызывает GeminiModel с составленным промптом и системной инструкцией. """ full_prompt = prompt if system_instruction: full_prompt = f"Системная инструкция:\n{system_instruction}\n\n{prompt}" return self.model.call(full_prompt) def generate_route_description(self, route_points: List[Dict], parser_chat_history: Optional[List[Dict]] = None) -> str: """ Генерирует описание маршрута на основе точек. """ self.route_points = route_points self.conversation_history = [] # Формируем контекст парсера if parser_chat_history: print(parser_chat_history) parser_messages = [f"{msg['role'].upper()}: {msg['content']}" for msg in parser_chat_history] self.parser_chat_context = "\n".join(parser_messages) else: self.parser_chat_context = "" # Формируем промпт с точками маршрута points_info = [] for i, point in enumerate(route_points, 1): name = point.get('title', f'Точка {i}') description = point.get('description', '') points_info.append(f"{i}. {name}\nОписание: {description}") prompt = f"""Создай краткое описание маршрута из {len(route_points)} точек. Для каждой точки напиши 1-2 предложения, которые заинтересуют посетителя. Используй только информацию из описаний точек. Точки маршрута: {chr(10).join(points_info)} """ if self.parser_chat_context: prompt = f"История запроса пользователя:\n{self.parser_chat_context}\n\n{prompt}" system_instruction = """Ты — помощник для описания туристических маршрутов. Твоя задача — создавать краткие, привлекательные описания точек маршрута (1-2 предложения на точку). Используй только информацию, представленную в описаниях точек. Пиши на русском языке.""" description = self._call_model(prompt, system_instruction) self.route_description = description return description def answer_question(self, question: str) -> str: """ Отвечает на вопрос пользователя о точках маршрута. """ # Формируем контекст с информацией о точках points_context = [f"{i+1}. {p['name']}: {p.get('description', 'Нет описания')}" for i, p in enumerate(self.route_points)] context = "\n\n".join(points_context) # Дополнительный контекст парсера и описания маршрута parser_info = f"\n\nИстория запроса пользователя:\n{self.parser_chat_context}" if self.parser_chat_context else "" route_desc_info = f"\n\nОписание маршрута:\n{self.route_description}" if self.route_description else "" system_instruction = f"""Ты — помощник по туристическому маршруту. {parser_info}{route_desc_info} Доступная информация о точках маршрута: {context} СТРОГИЕ ПРАВИЛА: 1. Отвечай ТОЛЬКО на вопросы о точках маршрута 2. Используй ТОЛЬКО информацию из описаний точек выше 3. Если в описаниях нет информации для ответа на вопрос, вежливо уходи от ответа фразами вида "Вы узнаете ответ, когда посетите это место", адаптируй под контекст. 4. НЕ давай рекомендаций и советов 5. НЕ отвечай на вопросы, не связанные с маршрутом. В таких случаях отвечай: "Я могу ответить только на вопросы о точках вашего маршрута" 6. НЕ придумывай информацию, которой нет в описаниях 7. Отвечай кратко и по существу на русском языке 8. Ты видишь всю историю разговора, поэтому можешь отвечать на уточняющие вопросы""" answer = self._call_model(question, system_instruction) return answer def reset_conversation(self): """Очищает историю разговора и маршрута.""" self.conversation_history = [] self.route_points = [] self.route_description = "" self.parser_chat_context = "" # Пример использования if __name__ == "__main__": # Инициализация (замените на ваш API ключ) API_KEY = "YOUR_GEMINI_API_KEY" describer = RouteDescriber() # Пример истории чата с парсером parser_chat = [ {"role": "user", "text": "Хочу погулять по центру Москвы, интересует история и искусство"}, {"role": "model", "text": "Понял, вы хотите прогулку по историческому центру с посещением музеев. Сколько времени у вас есть?"}, {"role": "user", "text": "Часа 3-4"}, {"role": "model", "text": "Отлично, я составил маршрут из 3 точек по центру Москвы с историческими местами и музеем искусства."} ] # Пример данных маршрута route_points = [ { "name": "Красная площадь", "description": "Главная площадь Москвы, окружённая историческими зданиями. Здесь находятся Кремль, собор Василия Блаженного и Мавзолей Ленина. Площадь была основана в конце XV века." }, { "name": "Парк Горького", "description": "Один из самых известных парков Москвы, расположенный на берегу Москвы-реки. Здесь есть зоны для отдыха, спортивные площадки, прокат велосипедов. Парк был открыт в 1928 году." }, { "name": "Третьяковская галерея", "description": "Художественный музей с крупнейшей коллекцией русского искусства. В экспозиции представлены работы от древнерусских икон до картин XX века. Основана купцом Павлом Третьяковым." } ] # Генерация описания маршрута с историей парсера print("=== ОПИСАНИЕ МАРШРУТА ===") description = describer.generate_route_description(route_points, parser_chat) print(description) print() # Примеры вопросов (теперь с контекстом истории) print("=== ДИАЛОГ С ПОЛЬЗОВАТЕЛЕМ ===") questions = [ "Когда был основан Парк Горького?", "А что там можно делать?", # Уточняющий вопрос о предыдущей теме "Какие картины есть в Третьяковской галерее?", "Сколько стоит билет?", # Без контекста, но система поймет что это про музей "Расскажи про Кремль", "Что посоветуешь взять с собой?", # Попытка получить рекомендацию "Как погода сегодня?" # Нерелевантный вопрос ] for q in questions: print(f"\n👤 Пользователь: {q}") answer = describer.answer_question(q) print(f"🤖 Бот: {answer}")