114 lines
5.0 KiB
Python
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) |