1+ """
2+ Этот модуль определяет основного AI-агента, его логику и цикл взаимодействия с пользователем.
3+ """
14from typing import Callable , Tuple , Optional , List , Dict , Any
25import os
36import json
47import logging
5- from openai import OpenAI
8+ from openai import OpenAI , APIError
69from openai .types .chat import ChatCompletionMessage
710from dotenv import load_dotenv
811from app .agents .tools import ToolDefinition
912
1013# Четкий и инструктивный системный промпт
1114SYSTEM_PROMPT = (
12- """You are a helpful AI assistant. You have access to a set of tools to answer the user’s questions.
13- When the user asks a question, first consider whether a tool is needed.
14- If you decide to use a tool, call it. Once you receive the result from the tool,
15- use that result to formulate a final response to the user.
16- Don’t just repeat the tool’s output — instead, provide a helpful and detailed answer that incorporates the retrieved data."" "
15+ "Ты — полезный ИИ-ассистент. У тебя есть доступ к набору инструментов для ответов на вопросы пользователя. "
16+ "Когда пользователь задает вопрос, сначала подумай, нужно ли использовать инструмент. "
17+ "Если решишь использовать инструмент, вызови его. После получения результата от инструмента, "
18+ "используй этот результат для формулирования окончательного ответа пользователю. "
19+ "Не просто констатируй вывод инструмента, а дай полезный и развернутый ответ, который включает в себя полученные данные. "
1720)
1821
1922# Настройка логирования
@@ -42,32 +45,31 @@ def __init__(
4245
4346 def _execute_tool (self , tool_name : str , tool_args : Dict [str , Any ]) -> str :
4447 """Выполняет инструмент и возвращает его результат в виде строки."""
45- logging .info (f"Выполнение инструмента '{ tool_name } ' с аргументами: { tool_args } " )
46- if tool_name in self .tools :
47- tool = self .tools [tool_name ]
48- try :
49- result = tool .function (tool_args )
50- logging .info (f"Инструмент '{ tool_name } ' успешно выполнен." )
51- return str (result )
52- except Exception as e :
53- logging .error (f"Ошибка при выполнении инструмента '{ tool_name } ': { e } " , exc_info = True )
54- return f"Ошибка: Не удалось выполнить инструмент '{ tool_name } '. Причина: { e } "
55- else :
56- logging .warning (f"Попытка вызова неизвестного инструмента: '{ tool_name } '" )
48+ logging .info ("Выполнение инструмента '%s' с аргументами: %s" , tool_name , tool_args )
49+ tool = self .tools .get (tool_name )
50+ if not tool :
51+ logging .warning ("Попытка вызова неизвестного инструмента: '%s'" , tool_name )
5752 return f"Ошибка: Инструмент '{ tool_name } ' не найден."
53+ try :
54+ result = tool .function (tool_args )
55+ logging .info ("Инструмент '%s' успешно выполнен." , tool_name )
56+ return str (result )
57+ except Exception as e :
58+ logging .error ("Непредвиденная ошибка при выполнении инструмента '%s': %s" , tool_name , e , exc_info = True )
59+ return f"Ошибка: Не удалось выполнить инструмент '{ tool_name } '. Причина: { e } "
5860
5961 def _get_user_input (self ) -> Optional [str ]:
6062 """Обрабатывает получение ввода от пользователя."""
6163 print ("\033 [94mВы:\033 [0m " , end = "" )
6264 if self .user_input_handler :
6365 user_input , ok = self .user_input_handler ()
6466 return user_input if ok else None
65- else :
66- try :
67- user_input = input ()
68- return user_input if user_input .strip () else None
69- except EOFError :
70- return None
67+
68+ try :
69+ user_input = input ()
70+ return user_input if user_input .strip () else None
71+ except EOFError :
72+ return None
7173
7274 def run (self ) -> None :
7375 """Запускает основной цикл общения с агентом."""
@@ -84,17 +86,21 @@ def run(self) -> None:
8486
8587 max_tool_calls = 5
8688 for _ in range (max_tool_calls ):
87- logging .info (f"Вызов OpenAI с историей из { len (conversation )} сообщений:\n { json .dumps (conversation , indent = 2 , ensure_ascii = False )} " )
89+ logging .info ("Вызов OpenAI с историей из %d сообщений:\n %s" ,
90+ len (conversation ),
91+ json .dumps (conversation , indent = 2 , ensure_ascii = False ))
8892
89- response : ChatCompletionMessage = self .client .chat .completions .create (
90- model = self .model ,
91- messages = conversation ,
92- tools = [
93- {"type" : "function" , "function" : tool .to_openai_spec ()}
94- for tool in self .tools .values ()
95- ] if self .tools else None ,
96- tool_choice = "auto" if self .tools else None ,
97- ).choices [0 ].message
93+ try :
94+ response : ChatCompletionMessage = self .client .chat .completions .create (
95+ model = self .model ,
96+ messages = conversation ,
97+ tools = [tool .to_openai_spec () for tool in self .tools .values ()] if self .tools else None ,
98+ tool_choice = "auto" if self .tools else None ,
99+ ).choices [0 ].message
100+ except APIError as e :
101+ logging .error ("Ошибка OpenAI API: %s" , e )
102+ print (f"\033 [91m{ self .name } : Произошла ошибка при обращении к OpenAI. Попробуйте еще раз.\033 [0m" )
103+ break
98104
99105 if not response .tool_calls :
100106 assistant_response = response .content or ""
@@ -111,7 +117,7 @@ def run(self) -> None:
111117 tool_args = json .loads (tool_args_str )
112118 tool_result = self ._execute_tool (tool_name , tool_args )
113119 except json .JSONDecodeError :
114- logging .error (f "Не удалось декодировать аргументы для '{ tool_name } ': { tool_args_str } " )
120+ logging .error ("Не удалось декодировать аргументы для '%s ': %s" , tool_name , tool_args_str )
115121 tool_result = f"Ошибка: Неверные аргументы для инструмента '{ tool_name } '."
116122
117123 conversation .append ({
0 commit comments