Files
task-69b1a07c-tekstovaya-ig…/solution.py
T

114 lines
5.0 KiB
Python

<|channel|>final solution.py<|message|>import sys
from typing import Optional
# Библиотеки, которые должны быть установлены в окружении задачи.
# Мы используем langchain для взаимодействия с LLM и rich для красивого вывода.
try:
from langchain.chat_models import ChatOpenAI
except ImportError as exc: # pragma: no cover
raise RuntimeError(
"Не удалось импортировать langchain. Убедитесь, что пакет установлен."
) from exc
try:
from rich.console import Console
from rich.prompt import Prompt
from rich.text import Text
except ImportError as exc: # pragma: no cover
raise RuntimeError(
"Не удалось импортировать rich. Убедитесь, что пакет установлен."
) from exc
class TextAdventureGame:
"""
Простая текстовая игра на основе LLM.
Игрок вводит команды, которые отправляются в модель,
а ответ модели выводится пользователю.
"""
def __init__(self, model_name: str = "gpt-3.5-turbo", temperature: float = 0.7):
"""
Инициализация игрового процесса.
:param model_name: имя LLM из OpenAI
:param temperature: степень случайности генерации текста
"""
self.console = Console()
# Создаём объект модели. Для работы требуется переменная окружения OPENAI_API_KEY.
try:
self.llm = ChatOpenAI(model=model_name, temperature=temperature)
except Exception as exc: # pragma: no cover
raise RuntimeError(
"Не удалось создать экземпляр LLM. Проверьте ключ OpenAI."
) from exc
def _display_welcome(self) -> None:
"""Показываем приветственное сообщение."""
welcome = Text("Добро пожаловать в текстовую игру!", style="bold green")
self.console.print(welcome)
def _get_player_input(self, prompt: str = "Что вы делаете?") -> Optional[str]:
"""
Получаем ввод от игрока. Если пользователь введёт 'quit',
возвращаем None для завершения игры.
"""
try:
user_input = Prompt.ask(prompt)
except KeyboardInterrupt: # pragma: no cover
self.console.print("\n[red]Игра прервана пользователем.[/red]")
return None
if user_input.strip().lower() in {"quit", "exit"}:
return None
return user_input
def _generate_response(self, player_action: str) -> str:
"""
Отправляем действие игрока в LLM и получаем ответ.
:param player_action: строка с командой игрока
:return: текст ответа модели
"""
# Формируем сообщение для чат‑модели.
messages = [
{"role": "system", "content": "Вы — мудрый рассказчик, описывающий события в мире приключений."},
{"role": "user", "content": player_action},
]
try:
response = self.llm.invoke(messages)
except Exception as exc: # pragma: no cover
raise RuntimeError("Ошибка при вызове LLM.") from exc
return response.content.strip()
def run(self) -> None:
"""Основной цикл игры."""
self._display_welcome()
while True:
action = self._get_player_input()
if action is None: # пользователь ввёл quit или прервал
self.console.print("[bold magenta]Спасибо за игру![/bold magenta]")
break
self.console.print(f"[cyan]Вы сказали:[/cyan] {action}")
try:
result = self._generate_response(action)
except Exception as exc: # pragma: no cover
self.console.print(f"[red]Ошибка генерации ответа: {exc}[/red]")
continue
self.console.print("\n[green]Ответ модели:[/green]\n")
self.console.print(result, style="italic")
self.console.print("-" * 40)
if __name__ == "__main__":
# Запускаем игру. Если переменная окружения OPENAI_API_KEY не задана,
# langchain выбросит исключение при создании модели.
game = TextAdventureGame()
try:
game.run()
except Exception as exc: # pragma: no cover
sys.stderr.write(f"Произошла ошибка: {exc}\n")
sys.exit(1)