Boris commited on
Commit
f72b7f7
·
1 Parent(s): 0a4ac5d
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .DS_Store +0 -0
  2. services/b2b/b2b_service.py → .history/src/b2b/b2b_service_20250630021334.py +0 -0
  3. .history/src/b2b/b2b_service_20250630135358.py +28 -0
  4. services/base_graph.py → .history/src/base_graph_20250629185111.py +0 -0
  5. .history/src/base_graph_20250630135358.py +126 -0
  6. services/base_service.py → .history/src/base_service_20250630134728.py +0 -0
  7. .history/src/base_service_20250630135358.py +76 -0
  8. services/borlas/borlas_service.py → .history/src/borlas/borlas_service_20250630021744.py +0 -0
  9. .history/src/borlas/borlas_service_20250630135358.py +28 -0
  10. services/corporate_email/corporate_email_service.py → .history/src/corporate_email/corporate_email_service_20250628144053.py +0 -0
  11. .history/src/corporate_email/corporate_email_service_20250630135358.py +24 -0
  12. services/crm/crm_service.py → .history/src/crm/crm_service_20250630021458.py +0 -0
  13. .history/src/crm/crm_service_20250630135358.py +28 -0
  14. services/internet_access/internet_access_service.py → .history/src/internet_access/internet_access_service_20250630012853.py +0 -0
  15. .history/src/internet_access/internet_access_service_20250630135358.py +27 -0
  16. services/one_c/one_c_service.py → .history/src/one_c/one_c_service_20250630021626.py +0 -0
  17. .history/src/one_c/one_c_service_20250630135358.py +28 -0
  18. services/openvpn/openvpn_prompts.py → .history/src/openvpn/openvpn_prompts_20250627163312.py +0 -0
  19. .history/src/openvpn/openvpn_prompts_20250630135358.py +103 -0
  20. services/openvpn/openvpn_service.py → .history/src/openvpn/openvpn_service_20250627125242.py +0 -0
  21. .history/src/openvpn/openvpn_service_20250630135358.py +44 -0
  22. services/print_and_scan/print_and_scan_service.py → .history/src/print_and_scan/print_and_scan_service_20250630021904.py +0 -0
  23. .history/src/print_and_scan/print_and_scan_service_20250630135358.py +28 -0
  24. services/service_by_name.py → .history/src/service_by_name_20250630022251.py +0 -0
  25. .history/src/service_by_name_20250630135358.py +29 -0
  26. services/streamlit_app.py → .history/src/streamlit_app_20250630025024.py +0 -0
  27. .history/src/streamlit_app_20250630135358.py +101 -0
  28. services/template/_service.py → .history/src/template/_service_20250627160824.py +0 -0
  29. .history/src/template/_service_20250630135358.py +28 -0
  30. {services → src}/.DS_Store +0 -0
  31. {services → src}/__init__.py +0 -0
  32. {services → src}/b2b/__init__.py +0 -0
  33. {services → src}/b2b/b2b_prompts.py +0 -0
  34. src/b2b/b2b_service.py +28 -0
  35. src/base_graph.py +126 -0
  36. src/base_service.py +76 -0
  37. {services → src}/borlas/__init__.py +0 -0
  38. {services → src}/borlas/borlas_prompts.py +0 -0
  39. src/borlas/borlas_service.py +28 -0
  40. {services → src}/broken_cases.txt +0 -0
  41. {services → src}/corporate_email/__init__.py +0 -0
  42. {services → src}/corporate_email/corporate_email_prompts.py +0 -0
  43. src/corporate_email/corporate_email_service.py +24 -0
  44. {services → src}/crm/__init__.py +0 -0
  45. {services → src}/crm/crm_prompts.py +0 -0
  46. src/crm/crm_service.py +28 -0
  47. {services → src}/get_answer_gigachat.py +0 -0
  48. {services → src}/get_classification.py +3 -3
  49. {services → src}/internet_access/__init__.py +0 -0
  50. {services → src}/internet_access/internet_access_cases.json +0 -0
.DS_Store CHANGED
Binary files a/.DS_Store and b/.DS_Store differ
 
services/b2b/b2b_service.py → .history/src/b2b/b2b_service_20250630021334.py RENAMED
File without changes
.history/src/b2b/b2b_service_20250630135358.py ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from langchain_core.tools import BaseTool, tool
2
+ from src.base_service import BaseService
3
+ from src.b2b.b2b_prompts import SYSTEM_PROMPT
4
+ from typing import List
5
+ import logging
6
+ import time
7
+
8
+ logger = logging.getLogger(__name__)
9
+
10
+
11
+ class B2BService(BaseService):
12
+ @property
13
+ def system_prompt(self) -> str:
14
+ return SYSTEM_PROMPT
15
+
16
+ @property
17
+ def tools(self) -> List[BaseTool]:
18
+ return self._base_tools + [
19
+ self.example_func,
20
+ ]
21
+
22
+ @tool
23
+ def example_func(question: str) -> None:
24
+ """Пример функции, как её здесь оформлять. Просто для примера, нужно удалить при реальном использовании"""
25
+ print("Я example_func")
26
+ time.sleep(4)
27
+ logger.info("Кто-то забыл удалить example_func!")
28
+
services/base_graph.py → .history/src/base_graph_20250629185111.py RENAMED
File without changes
.history/src/base_graph_20250630135358.py ADDED
@@ -0,0 +1,126 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import Annotated, Type
2
+ from langgraph.graph import StateGraph
3
+ from langchain_core.messages import HumanMessage, ToolMessage
4
+ from langgraph.graph.message import add_messages
5
+ from typing_extensions import TypedDict
6
+ from src.base_service import BaseService
7
+ from src.get_answer_gigachat import AnswerGigaChat
8
+ import logging
9
+ import os
10
+
11
+ logger = logging.getLogger(__name__)
12
+
13
+ class State(TypedDict):
14
+ messages: Annotated[list, add_messages]
15
+
16
+ class BaseGraph:
17
+ def __init__(self, service: Type[BaseService]):
18
+ self.service = service
19
+ # self._initialize_logging()
20
+ self.tools_dict = {tool.name: tool for tool in service.tools}
21
+ self.llm_with_tools = AnswerGigaChat().bind_tools(service.tools)
22
+ self.messages = service.get_initial_messages()
23
+ self.graph = self._build_graph()
24
+ logger.info(f"BaseGraph with service {service} was built")
25
+
26
+ def rebuild_with_new_service(self, service: Type[BaseService]):
27
+ self.service = service
28
+ self.tools_dict = {tool.name: tool for tool in service.tools}
29
+ self.llm_with_tools = AnswerGigaChat().bind_tools(service.tools)
30
+ self.graph = self._build_graph()
31
+ self.messages = service.get_messages_from_redirect(self.messages)
32
+ logger.info(f"BaseGraph was rebuilt with service {service}")
33
+
34
+ def _initialize_logging(self):
35
+ if os.path.exists(self.service.log_path):
36
+ os.remove(self.service.log_path)
37
+ logging.basicConfig(
38
+ level=logging.INFO,
39
+ format='%(asctime)s - %(levelname)s - %(message)s',
40
+ handlers=[logging.FileHandler(self.service.log_path)]
41
+ )
42
+
43
+ def _agent_node(self, state: State):
44
+ try:
45
+ logger.info("Starting agent_node")
46
+ messages = state["messages"]
47
+ response = self.llm_with_tools.invoke(messages)
48
+ response.content = self._clean_response(response.content)
49
+ return {"messages": [response]}
50
+ except Exception as e:
51
+ logger.error(f"Error in agent_node: {str(e)}", exc_info=True)
52
+ raise
53
+
54
+ def _tool_node(self, state: State):
55
+ try:
56
+ logger.info("Starting tool_node")
57
+ last_message = state["messages"][-1]
58
+ tool_calls = last_message.tool_calls
59
+
60
+ results = []
61
+ for call in tool_calls:
62
+ tool_name = call["name"]
63
+ logger.info(f"Running tool {tool_name}")
64
+ args = call["args"]
65
+
66
+ tool = self.tools_dict.get(tool_name)
67
+ if not tool:
68
+ raise ValueError(f"Tool {tool_name} not found")
69
+
70
+ tool_response = tool.invoke(args)
71
+ if tool_name == "make_redirect":
72
+ self.rebuild_with_new_service(tool_response)
73
+ results.append(str(tool_response))
74
+
75
+ return {"messages": [ToolMessage(content=", ".join(results), tool_call_id=call["id"])]}
76
+ except Exception as e:
77
+ logger.error(f"Error in tool_node: {str(e)}", exc_info=True)
78
+ raise
79
+
80
+ def _should_continue(self, state: State):
81
+ try:
82
+ logger.info("Checking should continue")
83
+ last_message = state["messages"][-1]
84
+ return "tool" if "function_call" in last_message.additional_kwargs else "end"
85
+ except Exception as e:
86
+ logger.error(f"Error in should_continue: {str(e)}", exc_info=True)
87
+ raise
88
+
89
+ def _build_graph(self):
90
+ try:
91
+ logger.info("Building graph")
92
+ graph_builder = StateGraph(State)
93
+
94
+ graph_builder.add_node("agent", self._agent_node)
95
+ graph_builder.add_node("tool", self._tool_node)
96
+
97
+ graph_builder.add_conditional_edges(
98
+ "agent",
99
+ self._should_continue,
100
+ {"tool": "tool", "end": "__end__"}
101
+ )
102
+ graph_builder.add_edge("tool", "agent")
103
+ graph_builder.set_entry_point("agent")
104
+
105
+ return graph_builder.compile()
106
+ except Exception as e:
107
+ logger.error(f"Error building graph: {str(e)}", exc_info=True)
108
+ raise
109
+
110
+ def _clean_response(self, content: str) -> str:
111
+ content = content.replace("</final_answer>", "<final_answer>").replace("</thinking>", "<thinking>")
112
+ if "<final_answer>" in content:
113
+ content = content.split("<final_answer>")[1]
114
+ if "<thinking>" in content:
115
+ content = content.split("<thinking>")[-1]
116
+ return content
117
+
118
+ def invoke(self, user_input):
119
+ try:
120
+ self.messages.append(HumanMessage(content=user_input))
121
+ result = self.graph.invoke({"messages": self.messages})
122
+ self.messages = result["messages"]
123
+ return result
124
+ except Exception as e:
125
+ logger.error(f"Error invoking graph: {str(e)}", exc_info=True)
126
+ raise
services/base_service.py → .history/src/base_service_20250630134728.py RENAMED
File without changes
.history/src/base_service_20250630135358.py ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from abc import ABC, abstractmethod
2
+ from langchain_core.messages import SystemMessage, HumanMessage, AIMessage
3
+ from system_prompt_template import DIALOG_PROMPT
4
+ from typing import List
5
+ from langchain_core.tools import BaseTool, tool
6
+ from src.service_by_name import get_service_by_name
7
+ import logging
8
+ import time
9
+ import os
10
+ from dotenv import load_dotenv
11
+
12
+ load_dotenv()
13
+ logger = logging.getLogger(__name__)
14
+
15
+ class BaseService(ABC):
16
+ def __init__(self):
17
+ self._base_tools = [self.closing_task,
18
+ self.make_jira_task,
19
+ ]
20
+
21
+ @property
22
+ @abstractmethod
23
+ def system_prompt(self) -> str:
24
+ """Возвращает системный промпт для сервиса"""
25
+ pass
26
+
27
+ @property
28
+ @abstractmethod
29
+ def tools(self) -> List[BaseTool]:
30
+ """Возвращает список инструментов сервиса"""
31
+ pass
32
+
33
+ @property
34
+ def log_path(self) -> str:
35
+ """Возвращает путь до папки с логами"""
36
+ return os.getenv("LOG_SERVICES_PATH")
37
+
38
+ def get_initial_messages(self):
39
+ """Возвращает начальные сообщения для графа"""
40
+ return [SystemMessage(content=self.system_prompt)]
41
+
42
+ def get_messages_from_redirect(self, messages):
43
+ messages_formatted = ""
44
+ for message in messages:
45
+ if isinstance(message, HumanMessage):
46
+ message += f"user: '{message.content}'\n"
47
+ elif isinstance(message, AIMessage):
48
+ message += f"assistant: '{message.content}'\n"
49
+
50
+ return [SystemMessage(content=self.system_prompt + DIALOG_PROMPT.format(messages_formatted))]
51
+
52
+ @tool
53
+ def make_redirect(service_name: str):
54
+ """Когда оказывается, что пользователю нужен эксперт в другом сервисе,
55
+ пользователя нужно перенаправить на соответствующего эксперта.
56
+ Функция принимает аргумент service_name из списка:
57
+ ['openvpn', 'corporate_email', 'internet_access'] и пересоздает класс эксперта
58
+ с соответствующими новому сервису знаниями."""
59
+ logger.info("redirecting question to service {service_name}")
60
+ return get_service_by_name(service_name)
61
+
62
+
63
+ @tool
64
+ def closing_task(question: str) -> None:
65
+ """Задача выполнена, сохраняем результаты"""
66
+ print("### Задача выполнена, сохраняем результаты")
67
+ time.sleep(2)
68
+ logger.info("task closed")
69
+
70
+ @tool
71
+ def make_jira_task(question: str) -> None:
72
+ """Задача не может быть выполнена с помощью ии, создаем задачу в jira для того,
73
+ чтобы её выполнил человек"""
74
+ time.sleep(2)
75
+ print("### Скриптом создается задача в jira с соответствующими деталями")
76
+ logger.info("jira task was make")
services/borlas/borlas_service.py → .history/src/borlas/borlas_service_20250630021744.py RENAMED
File without changes
.history/src/borlas/borlas_service_20250630135358.py ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from langchain_core.tools import BaseTool, tool
2
+ from src.base_service import BaseService
3
+ from src.borlas.borlas_prompts import SYSTEM_PROMPT
4
+ from typing import List
5
+ import logging
6
+ import time
7
+
8
+ logger = logging.getLogger(__name__)
9
+
10
+
11
+ class BorlasService(BaseService):
12
+ @property
13
+ def system_prompt(self) -> str:
14
+ return SYSTEM_PROMPT
15
+
16
+ @property
17
+ def tools(self) -> List[BaseTool]:
18
+ return self._base_tools + [
19
+ self.example_func,
20
+ ]
21
+
22
+ @tool
23
+ def example_func(question: str) -> None:
24
+ """Пример функции, как её здесь оформлять. Просто для примера, нужно удалить при реальном использовании"""
25
+ print("Я example_func")
26
+ time.sleep(4)
27
+ logger.info("Кто-то забыл удалить example_func!")
28
+
services/corporate_email/corporate_email_service.py → .history/src/corporate_email/corporate_email_service_20250628144053.py RENAMED
File without changes
.history/src/corporate_email/corporate_email_service_20250630135358.py ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from langchain_core.tools import BaseTool, tool
2
+ from src.base_service import BaseService
3
+ from src.corporate_email.corporate_email_prompts import SYSTEM_PROMPT
4
+ from typing import List
5
+ import logging
6
+ import time
7
+
8
+ logger = logging.getLogger(__name__)
9
+
10
+
11
+ class CorporateEmailService(BaseService):
12
+ @property
13
+ def system_prompt(self) -> str:
14
+ return SYSTEM_PROMPT
15
+
16
+ @property
17
+ def tools(self) -> List[BaseTool]:
18
+ return self._base_tools + []
19
+
20
+ @tool
21
+ def check_lock_in_active_dir_and_password(question: str) -> None:
22
+ """Проверка блокировки учетной записи сотрудника в системе и разблокировка и проверка на просроченный пароль и обновление пароля. Если эти проблемы вскрываются, то функция их исправляет."""
23
+ time.sleep(4)
24
+ logger.info("check_lock_in_active_dir_and_password")
services/crm/crm_service.py → .history/src/crm/crm_service_20250630021458.py RENAMED
File without changes
.history/src/crm/crm_service_20250630135358.py ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from langchain_core.tools import BaseTool, tool
2
+ from src.base_service import BaseService
3
+ from src.crm.crm_prompts import SYSTEM_PROMPT
4
+ from typing import List
5
+ import logging
6
+ import time
7
+
8
+ logger = logging.getLogger(__name__)
9
+
10
+
11
+ class CRMService(BaseService):
12
+ @property
13
+ def system_prompt(self) -> str:
14
+ return SYSTEM_PROMPT
15
+
16
+ @property
17
+ def tools(self) -> List[BaseTool]:
18
+ return self._base_tools + [
19
+ self.example_func,
20
+ ]
21
+
22
+ @tool
23
+ def example_func(question: str) -> None:
24
+ """Пример функции, как её здесь оформлять. Просто для примера, нужно удалить при реальном использовании"""
25
+ print("Я example_func")
26
+ time.sleep(4)
27
+ logger.info("Кто-то забыл удалить example_func!")
28
+
services/internet_access/internet_access_service.py → .history/src/internet_access/internet_access_service_20250630012853.py RENAMED
File without changes
.history/src/internet_access/internet_access_service_20250630135358.py ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from langchain_core.tools import BaseTool, tool
2
+ from src.base_service import BaseService
3
+ from src.internet_access.internet_access_prompts import SYSTEM_PROMPT
4
+ from typing import List
5
+ import logging
6
+ import time
7
+
8
+ logger = logging.getLogger(__name__)
9
+
10
+ class InternetAccessService(BaseService):
11
+ @property
12
+ def system_prompt(self) -> str:
13
+ return SYSTEM_PROMPT
14
+
15
+ @property
16
+ def tools(self) -> List[BaseTool]:
17
+ return self._base_tools + [
18
+ self.example_func,
19
+ ]
20
+
21
+ @tool
22
+ def example_func(question: str) -> None:
23
+ """Пример функции, как её здесь оформлять. Просто для примера, нужно удалить при реальном использовании"""
24
+ print("Я example_func")
25
+ time.sleep(4)
26
+ logger.info("Кто-то забыл удалить example_func!")
27
+
services/one_c/one_c_service.py → .history/src/one_c/one_c_service_20250630021626.py RENAMED
File without changes
.history/src/one_c/one_c_service_20250630135358.py ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from langchain_core.tools import BaseTool, tool
2
+ from src.base_service import BaseService
3
+ from src.one_c.one_c_prompts import SYSTEM_PROMPT
4
+ from typing import List
5
+ import logging
6
+ import time
7
+
8
+ logger = logging.getLogger(__name__)
9
+
10
+
11
+ class OneCService(BaseService):
12
+ @property
13
+ def system_prompt(self) -> str:
14
+ return SYSTEM_PROMPT
15
+
16
+ @property
17
+ def tools(self) -> List[BaseTool]:
18
+ return self._base_tools + [
19
+ self.example_func,
20
+ ]
21
+
22
+ @tool
23
+ def example_func(question: str) -> None:
24
+ """Пример функции, как её здесь оформлять. Просто для примера, нужно удалить при реальном использовании"""
25
+ print("Я example_func")
26
+ time.sleep(4)
27
+ logger.info("Кто-то забыл удалить example_func!")
28
+
services/openvpn/openvpn_prompts.py → .history/src/openvpn/openvpn_prompts_20250627163312.py RENAMED
File without changes
.history/src/openvpn/openvpn_prompts_20250630135358.py ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from src.system_prompt_template import SYSTEM_PROMPT_TEMPLATE
2
+
3
+ service_name = "open vpn"
4
+
5
+ service_description = ""
6
+
7
+ cases = """
8
+ У пользователя может быть одна из 3 ситуаций, надо определить, какая у него:
9
+
10
+ - Консультация.
11
+ Это когда:
12
+ - Программа есть
13
+ - Программа открывается
14
+ - vpn подключается
15
+ В этом случае надо предпринять действия:
16
+ - Проконсультировать пользователя, как пользоваться vpn.
17
+ и ответить на его вопросы.
18
+ - Если пользователь подтвердил, что все работает, вызови функцию closing_task, поблагодари за обращение.
19
+ в техническую поддержку
20
+ - Если ты не можешь помочь пользователю или он задает вопросы, на которые у тебя нет инструкций,
21
+ вызови функцию make_jira_task, сообщи, что была создана задача в jira и в ближайшее времся с
22
+ пользователем свяжется сотрудник технической поддержки.
23
+
24
+ - Установка
25
+ Это когда:
26
+ - Программы нет на компьютере пользователя.
27
+ В этом случае надо предпринять действия:
28
+ - Вызывать функцию install_program
29
+ - Если пользователь подтвердил, что все работает, вызови функцию closing_task, поблагодари за обращение
30
+ в техническую поддержку
31
+ - Если пользователь говорит, что vpn по-прежнему не работает, вызови функцию script_part
32
+
33
+ - Переустановка
34
+ Это когда:
35
+ - Программы не открывается.
36
+ В этом случае надо предпринять действия:
37
+ - Вызывать функцию delete_and_install_program
38
+ - Если пользователь подтвердил, что все работает, вызови функцию closing_task, поблагодари за обращение
39
+ в техническую поддержку
40
+ - Если пользователь говорит, что vpn по-прежнему не работает, вызови функцию script_part
41
+ """
42
+
43
+
44
+ broken_cases = """
45
+ 'В таком случае вам необходимо установить программу OpenVPN. Для этого выполните следующие действия:
46
+
47
+ Перейдите на официальный сайт OpenVPN (https://openvpn.net/) и скачайте последнюю версию программы.
48
+ Запустите установочный файл и следуйте инструкциям мастера установки.
49
+ После завершения установки запустите программу и попробуйте подключить VPN.
50
+ Если возникнут трудности при установке или использовании программы, пожалуйста, дайте мне знать.' - этот ответ нарушает правила 8 и 9
51
+
52
+ 'Тогда, возможно, проблема связана с настройками самого приложения или сервера.
53
+ В этом случае я рекомендую обратиться к вашему системному администратору или в службу поддержки вашего VPN-провайдера.
54
+ Они смогут провести более детальную диагностику и устранить проблему.' - этот ответ нарушает правила 8 и 12
55
+ """
56
+
57
+
58
+ knowledge = """
59
+ Инструкции:
60
+ Как пользоваться openvpn:
61
+ Документ представляет собой инструкцию по подключению к корпоративной сети через VPN,
62
+ используя приложение OpenVPN Connect. Он предназначен для сотрудников компании,
63
+ которым необходимо получить удалённый доступ к внутренним ресурсам из внешней сети
64
+ (например, при работе из дома или вне офиса).
65
+
66
+ Ключевые шаги подключения к VPN:
67
+
68
+ Подключение к внешней сети:
69
+ Убедитесь, что устройство подключено к любой внешней сети: через Ethernet, Wi-Fi или мобильную точку доступа.
70
+ Статус подключения можно проверить через иконку интернета в нижнем правом углу экрана.
71
+ Запуск OpenVPN Connect:
72
+ Найдите и запустите приложение OpenVPN Connect.
73
+ Оно может находиться на рабочем столе или его можно найти через строку поиска Windows, введя «OpenVPN Connect».
74
+ Активация VPN-соединения:
75
+ Переключите ползунок подключения в приложении, чтобы инициировать подключение к VPN.
76
+ В появившемся окне введите свои учётные данные (логин и пароль).
77
+ Нажмите кнопку «ОК» для подтверждения.
78
+ Готово:
79
+ После авторизации будет установлен удалённый доступ к сетевым ресурсам компании.
80
+ Цель документа:
81
+ Обеспечить безопасный доступ сотрудников к корпоративным системам из внешней интернет-сети посредством OpenVPN.
82
+
83
+ Требования:
84
+ Установленное приложение OpenVPN Connect.
85
+ Доступ к внешнему интернету.
86
+ Действующие учётные данные сотрудника.
87
+
88
+ Как проверить, установлена ли программа open vpn:
89
+ В поиске набрать OpenVPN. Если результаты поиска отсутствуют, то программа не установлена.
90
+
91
+
92
+ Как проверить, подключился ли open vpn:
93
+ Успех подключения выглядит как на скриншоте, должна появиться надпись CONNECTED.
94
+
95
+ Как правильно вводить учетные данные:
96
+ Логин вводится в формате Имя.Фамилия на латинице с заглавных букв. Пример: Ivan.Ivanov. Пароль вводится такой же, как при входе в пк.
97
+ """
98
+
99
+ SYSTEM_PROMPT = SYSTEM_PROMPT_TEMPLATE.format(service_name=service_name,
100
+ service_description=service_description,
101
+ cases=cases,
102
+ broken_cases=broken_cases,
103
+ knowledge=knowledge)
services/openvpn/openvpn_service.py → .history/src/openvpn/openvpn_service_20250627125242.py RENAMED
File without changes
.history/src/openvpn/openvpn_service_20250630135358.py ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from langchain_core.tools import BaseTool, tool
2
+ from src.base_service import BaseService
3
+ from src.openvpn.openvpn_prompts import SYSTEM_PROMPT
4
+ from typing import List
5
+ import logging
6
+ import time
7
+
8
+ logger = logging.getLogger(__name__)
9
+
10
+
11
+ class OpenVPNService(BaseService):
12
+ @property
13
+ def system_prompt(self) -> str:
14
+ return SYSTEM_PROMPT
15
+
16
+ @property
17
+ def tools(self) -> List[BaseTool]:
18
+ return self._base_tools + [
19
+ self.script_part,
20
+ self.install_program,
21
+ self.delete_and_install_program
22
+ ]
23
+
24
+ @tool
25
+ def script_part(question: str) -> None:
26
+ """Запускаем большой скрипт для проверки возможных проблем с приложением
27
+ и их устранением"""
28
+ print("ran_graph(question)")
29
+ time.sleep(4)
30
+ logger.info("script part")
31
+
32
+ @tool
33
+ def install_program(question: str) -> None:
34
+ """Запускаем скрипты, которые ставят программу openvpn"""
35
+ print("### Скриптом устанавливаем программу")
36
+ time.sleep(3)
37
+ logger.info("installing program")
38
+
39
+ @tool
40
+ def delete_and_install_program(question: str) -> None:
41
+ """Запускаем скрипты, которые удаляют и ставят программу openvpn"""
42
+ print("### Скриптом удаляем и ставим программу")
43
+ time.sleep(3)
44
+ logger.info("deleting and installing program")
services/print_and_scan/print_and_scan_service.py → .history/src/print_and_scan/print_and_scan_service_20250630021904.py RENAMED
File without changes
.history/src/print_and_scan/print_and_scan_service_20250630135358.py ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from langchain_core.tools import BaseTool, tool
2
+ from src.base_service import BaseService
3
+ from src.print_and_scan.print_and_scan_prompts import SYSTEM_PROMPT
4
+ from typing import List
5
+ import logging
6
+ import time
7
+
8
+ logger = logging.getLogger(__name__)
9
+
10
+
11
+ class PrintAndScanService(BaseService):
12
+ @property
13
+ def system_prompt(self) -> str:
14
+ return SYSTEM_PROMPT
15
+
16
+ @property
17
+ def tools(self) -> List[BaseTool]:
18
+ return self._base_tools + [
19
+ self.example_func,
20
+ ]
21
+
22
+ @tool
23
+ def example_func(question: str) -> None:
24
+ """Пример функции, как её здесь оформлять. Просто для примера, нужно удалить при реальном использовании"""
25
+ print("Я example_func")
26
+ time.sleep(4)
27
+ logger.info("Кто-то забыл удалить example_func!")
28
+
services/service_by_name.py → .history/src/service_by_name_20250630022251.py RENAMED
File without changes
.history/src/service_by_name_20250630135358.py ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ def get_service_by_name(service_name):
3
+ if service_name == "openvpn":
4
+ from src.openvpn.openvpn_service import OpenVPNService
5
+ return OpenVPNService()
6
+ if service_name == "corporate_email":
7
+ from src.corporate_email.corporate_email_service import CorporateEmailService
8
+ return CorporateEmailService()
9
+ if service_name == "internet_access":
10
+ from src.internet_access.internet_access_service import InternetAccessService
11
+ return InternetAccessService()
12
+ if service_name == "b2b":
13
+ from src.b2b.b2b_service import B2BService
14
+ return B2BService()
15
+ if service_name == "crm":
16
+ from src.crm.crm_service import CRMService
17
+ return CRMService()
18
+ if service_name == "one_c":
19
+ from src.one_c.one_c_service import OneCService
20
+ return OneCService()
21
+ if service_name == "borlas":
22
+ from src.borlas.borlas_service import BorlasService
23
+ return BorlasService()
24
+ if service_name == "print_and_scan":
25
+ from src.print_and_scan.print_and_scan_service import PrintAndScanService
26
+ return PrintAndScanService()
27
+
28
+
29
+ raise ValueError(f"Некорректное имя сервиса '{service_name}'")
services/streamlit_app.py → .history/src/streamlit_app_20250630025024.py RENAMED
File without changes
.history/src/streamlit_app_20250630135358.py ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ from langchain_core.messages import HumanMessage, AIMessage
3
+ from src.get_classification import get_graph_class
4
+ from datetime import datetime
5
+
6
+
7
+ def message_to_dict(messages):
8
+ result = []
9
+ for message in messages:
10
+ if isinstance(message, HumanMessage) or isinstance(message, AIMessage):
11
+ print("message:", message.content)
12
+ if message.content == "" or message.content is None:
13
+ continue
14
+ if isinstance(message, HumanMessage):
15
+ result.append({"role": "user", "content": message.content})
16
+ elif isinstance(message, AIMessage):
17
+ result.append({"role": "assistant", "content": message.content})
18
+ print("-" * 100)
19
+ return result
20
+
21
+
22
+ def find_last_bot_message(messages):
23
+ """Находит последнее сообщение бота"""
24
+ for message in messages[::-1]:
25
+ if isinstance(message, AIMessage) and len(message.content) > 0:
26
+ return message.content
27
+ return None
28
+
29
+
30
+ def display_chat_messages():
31
+ """Отображает историю сообщений в чате"""
32
+ for message in st.session_state.messages:
33
+ with st.chat_message(message["role"]):
34
+ st.markdown(message["content"])
35
+
36
+
37
+ def save_broken_case():
38
+ messages_dict = st.session_state.messages
39
+ result_str = ""
40
+ for elem in messages_dict:
41
+ role = elem["role"]
42
+ content = elem["content"]
43
+ result_str += f"{role}: {content}\n"
44
+
45
+ current_datetime = datetime.now()
46
+ formatted_datetime = current_datetime.strftime("%Y-%m-%d %H:%M:%S")
47
+
48
+ with open("/Users/admin/my_documents/retrieval_part/services/broken_cases.txt", "a") as file:
49
+ file.write(f"{formatted_datetime}\n" + result_str + "\n" + "-" * 50 + "\n\n")
50
+
51
+
52
+ def handle_user_input():
53
+ """Обрабатывает ввод пользователя и генерирует ответ бота"""
54
+ if prompt := st.chat_input("Введите ваш вопрос"):
55
+ st.session_state.messages.append({"role": "user", "content": prompt})
56
+ if prompt.lower().startswith("log"):
57
+ save_broken_case()
58
+ st.session_state.messages = []
59
+ display_chat_messages()
60
+ else:
61
+ with st.chat_message("user"):
62
+ st.markdown(prompt)
63
+
64
+ if "bot" not in st.session_state:
65
+ st.session_state.bot = get_graph_class(prompt)
66
+ st.session_state.bot.invoke(prompt)
67
+
68
+ # Извлекаем последнее сообщение бота
69
+ last_bot_message = find_last_bot_message(st.session_state.bot.messages)
70
+ st.session_state.messages.append(
71
+ {"role": "assistant", "content": last_bot_message}
72
+ )
73
+ with st.chat_message("assistant"):
74
+ st.markdown(last_bot_message)
75
+
76
+
77
+ def clear_chat():
78
+ """Очищает чат и пересоздает бота"""
79
+ st.session_state.messages = []
80
+ del st.session_state.bot
81
+
82
+
83
+ def main():
84
+ """Основная функция приложения"""
85
+ # Заголовок приложения
86
+ st.title("Чат-бот технической поддержки OpenVPN")
87
+
88
+ # Кнопка очистки чата
89
+ if st.button("Clear"):
90
+ clear_chat()
91
+
92
+ if "messages" not in st.session_state:
93
+ st.session_state.messages = []
94
+
95
+ # Отображение чата и обработка ввода
96
+ display_chat_messages()
97
+ handle_user_input()
98
+
99
+
100
+ if __name__ == "__main__":
101
+ main()
services/template/_service.py → .history/src/template/_service_20250627160824.py RENAMED
File without changes
.history/src/template/_service_20250630135358.py ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from langchain_core.tools import BaseTool, tool
2
+ from src.base_service import BaseService
3
+ from src.template._prompts import SYSTEM_PROMPT ## FIX
4
+ from typing import List
5
+ import logging
6
+ import time
7
+
8
+ logger = logging.getLogger(__name__)
9
+
10
+
11
+ class ExamplePLSRenameService(BaseService):
12
+ @property
13
+ def system_prompt(self) -> str:
14
+ return SYSTEM_PROMPT
15
+
16
+ @property
17
+ def tools(self) -> List[BaseTool]:
18
+ return self._base_tools + [
19
+ self.example_func,
20
+ ]
21
+
22
+ @tool
23
+ def example_func(question: str) -> None:
24
+ """Пример функции, как её здесь оформлять. Просто для примера, нужно удалить при реальном использовании"""
25
+ print("Я example_func")
26
+ time.sleep(4)
27
+ logger.info("Кто-то забыл удалить example_func!")
28
+
{services → src}/.DS_Store RENAMED
File without changes
{services → src}/__init__.py RENAMED
File without changes
{services → src}/b2b/__init__.py RENAMED
File without changes
{services → src}/b2b/b2b_prompts.py RENAMED
File without changes
src/b2b/b2b_service.py ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from langchain_core.tools import BaseTool, tool
2
+ from src.base_service import BaseService
3
+ from src.b2b.b2b_prompts import SYSTEM_PROMPT
4
+ from typing import List
5
+ import logging
6
+ import time
7
+
8
+ logger = logging.getLogger(__name__)
9
+
10
+
11
+ class B2BService(BaseService):
12
+ @property
13
+ def system_prompt(self) -> str:
14
+ return SYSTEM_PROMPT
15
+
16
+ @property
17
+ def tools(self) -> List[BaseTool]:
18
+ return self._base_tools + [
19
+ self.example_func,
20
+ ]
21
+
22
+ @tool
23
+ def example_func(question: str) -> None:
24
+ """Пример функции, как её здесь оформлять. Просто для примера, нужно удалить при реальном использовании"""
25
+ print("Я example_func")
26
+ time.sleep(4)
27
+ logger.info("Кто-то забыл удалить example_func!")
28
+
src/base_graph.py ADDED
@@ -0,0 +1,126 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import Annotated, Type
2
+ from langgraph.graph import StateGraph
3
+ from langchain_core.messages import HumanMessage, ToolMessage
4
+ from langgraph.graph.message import add_messages
5
+ from typing_extensions import TypedDict
6
+ from src.base_service import BaseService
7
+ from src.get_answer_gigachat import AnswerGigaChat
8
+ import logging
9
+ import os
10
+
11
+ logger = logging.getLogger(__name__)
12
+
13
+ class State(TypedDict):
14
+ messages: Annotated[list, add_messages]
15
+
16
+ class BaseGraph:
17
+ def __init__(self, service: Type[BaseService]):
18
+ self.service = service
19
+ # self._initialize_logging()
20
+ self.tools_dict = {tool.name: tool for tool in service.tools}
21
+ self.llm_with_tools = AnswerGigaChat().bind_tools(service.tools)
22
+ self.messages = service.get_initial_messages()
23
+ self.graph = self._build_graph()
24
+ logger.info(f"BaseGraph with service {service} was built")
25
+
26
+ def rebuild_with_new_service(self, service: Type[BaseService]):
27
+ self.service = service
28
+ self.tools_dict = {tool.name: tool for tool in service.tools}
29
+ self.llm_with_tools = AnswerGigaChat().bind_tools(service.tools)
30
+ self.graph = self._build_graph()
31
+ self.messages = service.get_messages_from_redirect(self.messages)
32
+ logger.info(f"BaseGraph was rebuilt with service {service}")
33
+
34
+ def _initialize_logging(self):
35
+ if os.path.exists(self.service.log_path):
36
+ os.remove(self.service.log_path)
37
+ logging.basicConfig(
38
+ level=logging.INFO,
39
+ format='%(asctime)s - %(levelname)s - %(message)s',
40
+ handlers=[logging.FileHandler(self.service.log_path)]
41
+ )
42
+
43
+ def _agent_node(self, state: State):
44
+ try:
45
+ logger.info("Starting agent_node")
46
+ messages = state["messages"]
47
+ response = self.llm_with_tools.invoke(messages)
48
+ response.content = self._clean_response(response.content)
49
+ return {"messages": [response]}
50
+ except Exception as e:
51
+ logger.error(f"Error in agent_node: {str(e)}", exc_info=True)
52
+ raise
53
+
54
+ def _tool_node(self, state: State):
55
+ try:
56
+ logger.info("Starting tool_node")
57
+ last_message = state["messages"][-1]
58
+ tool_calls = last_message.tool_calls
59
+
60
+ results = []
61
+ for call in tool_calls:
62
+ tool_name = call["name"]
63
+ logger.info(f"Running tool {tool_name}")
64
+ args = call["args"]
65
+
66
+ tool = self.tools_dict.get(tool_name)
67
+ if not tool:
68
+ raise ValueError(f"Tool {tool_name} not found")
69
+
70
+ tool_response = tool.invoke(args)
71
+ if tool_name == "make_redirect":
72
+ self.rebuild_with_new_service(tool_response)
73
+ results.append(str(tool_response))
74
+
75
+ return {"messages": [ToolMessage(content=", ".join(results), tool_call_id=call["id"])]}
76
+ except Exception as e:
77
+ logger.error(f"Error in tool_node: {str(e)}", exc_info=True)
78
+ raise
79
+
80
+ def _should_continue(self, state: State):
81
+ try:
82
+ logger.info("Checking should continue")
83
+ last_message = state["messages"][-1]
84
+ return "tool" if "function_call" in last_message.additional_kwargs else "end"
85
+ except Exception as e:
86
+ logger.error(f"Error in should_continue: {str(e)}", exc_info=True)
87
+ raise
88
+
89
+ def _build_graph(self):
90
+ try:
91
+ logger.info("Building graph")
92
+ graph_builder = StateGraph(State)
93
+
94
+ graph_builder.add_node("agent", self._agent_node)
95
+ graph_builder.add_node("tool", self._tool_node)
96
+
97
+ graph_builder.add_conditional_edges(
98
+ "agent",
99
+ self._should_continue,
100
+ {"tool": "tool", "end": "__end__"}
101
+ )
102
+ graph_builder.add_edge("tool", "agent")
103
+ graph_builder.set_entry_point("agent")
104
+
105
+ return graph_builder.compile()
106
+ except Exception as e:
107
+ logger.error(f"Error building graph: {str(e)}", exc_info=True)
108
+ raise
109
+
110
+ def _clean_response(self, content: str) -> str:
111
+ content = content.replace("</final_answer>", "<final_answer>").replace("</thinking>", "<thinking>")
112
+ if "<final_answer>" in content:
113
+ content = content.split("<final_answer>")[1]
114
+ if "<thinking>" in content:
115
+ content = content.split("<thinking>")[-1]
116
+ return content
117
+
118
+ def invoke(self, user_input):
119
+ try:
120
+ self.messages.append(HumanMessage(content=user_input))
121
+ result = self.graph.invoke({"messages": self.messages})
122
+ self.messages = result["messages"]
123
+ return result
124
+ except Exception as e:
125
+ logger.error(f"Error invoking graph: {str(e)}", exc_info=True)
126
+ raise
src/base_service.py ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from abc import ABC, abstractmethod
2
+ from langchain_core.messages import SystemMessage, HumanMessage, AIMessage
3
+ from system_prompt_template import DIALOG_PROMPT
4
+ from typing import List
5
+ from langchain_core.tools import BaseTool, tool
6
+ from src.service_by_name import get_service_by_name
7
+ import logging
8
+ import time
9
+ import os
10
+ from dotenv import load_dotenv
11
+
12
+ load_dotenv()
13
+ logger = logging.getLogger(__name__)
14
+
15
+ class BaseService(ABC):
16
+ def __init__(self):
17
+ self._base_tools = [self.closing_task,
18
+ self.make_jira_task,
19
+ ]
20
+
21
+ @property
22
+ @abstractmethod
23
+ def system_prompt(self) -> str:
24
+ """Возвращает системный промпт для сервиса"""
25
+ pass
26
+
27
+ @property
28
+ @abstractmethod
29
+ def tools(self) -> List[BaseTool]:
30
+ """Возвращает список инструментов сервиса"""
31
+ pass
32
+
33
+ @property
34
+ def log_path(self) -> str:
35
+ """Возвращает путь до папки с логами"""
36
+ return os.getenv("LOG_SERVICES_PATH")
37
+
38
+ def get_initial_messages(self):
39
+ """Возвращает начальные сообщения для графа"""
40
+ return [SystemMessage(content=self.system_prompt)]
41
+
42
+ def get_messages_from_redirect(self, messages):
43
+ messages_formatted = ""
44
+ for message in messages:
45
+ if isinstance(message, HumanMessage):
46
+ message += f"user: '{message.content}'\n"
47
+ elif isinstance(message, AIMessage):
48
+ message += f"assistant: '{message.content}'\n"
49
+
50
+ return [SystemMessage(content=self.system_prompt + DIALOG_PROMPT.format(messages_formatted))]
51
+
52
+ @tool
53
+ def make_redirect(service_name: str):
54
+ """Когда оказывается, что пользователю нужен эксперт в другом сервисе,
55
+ пользователя нужно перенаправить на соответствующего эксперта.
56
+ Функция принимает аргумент service_name из списка:
57
+ ['openvpn', 'corporate_email', 'internet_access'] и пересоздает класс эксперта
58
+ с соответствующими новому сервису знаниями."""
59
+ logger.info("redirecting question to service {service_name}")
60
+ return get_service_by_name(service_name)
61
+
62
+
63
+ @tool
64
+ def closing_task(question: str) -> None:
65
+ """Задача выполнена, сохраняем результаты"""
66
+ print("### Задача выполнена, сохраняем результаты")
67
+ time.sleep(2)
68
+ logger.info("task closed")
69
+
70
+ @tool
71
+ def make_jira_task(question: str) -> None:
72
+ """Задача не может быть выполнена с помощью ии, создаем задачу в jira для того,
73
+ чтобы её выполнил человек"""
74
+ time.sleep(2)
75
+ print("### Скриптом создается задача в jira с соответствующими деталями")
76
+ logger.info("jira task was make")
{services → src}/borlas/__init__.py RENAMED
File without changes
{services → src}/borlas/borlas_prompts.py RENAMED
File without changes
src/borlas/borlas_service.py ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from langchain_core.tools import BaseTool, tool
2
+ from src.base_service import BaseService
3
+ from src.borlas.borlas_prompts import SYSTEM_PROMPT
4
+ from typing import List
5
+ import logging
6
+ import time
7
+
8
+ logger = logging.getLogger(__name__)
9
+
10
+
11
+ class BorlasService(BaseService):
12
+ @property
13
+ def system_prompt(self) -> str:
14
+ return SYSTEM_PROMPT
15
+
16
+ @property
17
+ def tools(self) -> List[BaseTool]:
18
+ return self._base_tools + [
19
+ self.example_func,
20
+ ]
21
+
22
+ @tool
23
+ def example_func(question: str) -> None:
24
+ """Пример функции, как её здесь оформлять. Просто для примера, нужно удалить при реальном использовании"""
25
+ print("Я example_func")
26
+ time.sleep(4)
27
+ logger.info("Кто-то забыл удалить example_func!")
28
+
{services → src}/broken_cases.txt RENAMED
File without changes
{services → src}/corporate_email/__init__.py RENAMED
File without changes
{services → src}/corporate_email/corporate_email_prompts.py RENAMED
File without changes
src/corporate_email/corporate_email_service.py ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from langchain_core.tools import BaseTool, tool
2
+ from src.base_service import BaseService
3
+ from src.corporate_email.corporate_email_prompts import SYSTEM_PROMPT
4
+ from typing import List
5
+ import logging
6
+ import time
7
+
8
+ logger = logging.getLogger(__name__)
9
+
10
+
11
+ class CorporateEmailService(BaseService):
12
+ @property
13
+ def system_prompt(self) -> str:
14
+ return SYSTEM_PROMPT
15
+
16
+ @property
17
+ def tools(self) -> List[BaseTool]:
18
+ return self._base_tools + []
19
+
20
+ @tool
21
+ def check_lock_in_active_dir_and_password(question: str) -> None:
22
+ """Проверка блокировки учетной записи сотрудника в системе и разблокировка и проверка на просроченный пароль и обновление пароля. Если эти проблемы вскрываются, то функция их исправляет."""
23
+ time.sleep(4)
24
+ logger.info("check_lock_in_active_dir_and_password")
{services → src}/crm/__init__.py RENAMED
File without changes
{services → src}/crm/crm_prompts.py RENAMED
File without changes
src/crm/crm_service.py ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from langchain_core.tools import BaseTool, tool
2
+ from src.base_service import BaseService
3
+ from src.crm.crm_prompts import SYSTEM_PROMPT
4
+ from typing import List
5
+ import logging
6
+ import time
7
+
8
+ logger = logging.getLogger(__name__)
9
+
10
+
11
+ class CRMService(BaseService):
12
+ @property
13
+ def system_prompt(self) -> str:
14
+ return SYSTEM_PROMPT
15
+
16
+ @property
17
+ def tools(self) -> List[BaseTool]:
18
+ return self._base_tools + [
19
+ self.example_func,
20
+ ]
21
+
22
+ @tool
23
+ def example_func(question: str) -> None:
24
+ """Пример функции, как её здесь оформлять. Просто для примера, нужно удалить при реальном использовании"""
25
+ print("Я example_func")
26
+ time.sleep(4)
27
+ logger.info("Кто-то забыл удалить example_func!")
28
+
{services → src}/get_answer_gigachat.py RENAMED
File without changes
{services → src}/get_classification.py RENAMED
@@ -3,9 +3,9 @@ from typing import Literal
3
  import logging
4
  from langchain.prompts import ChatPromptTemplate
5
  from langchain_core.output_parsers import JsonOutputParser
6
- from services.get_answer_gigachat import AnswerGigaChat
7
- from services.service_by_name import get_service_by_name
8
- from services.base_graph import BaseGraph
9
  import os
10
  from dotenv import load_dotenv
11
 
 
3
  import logging
4
  from langchain.prompts import ChatPromptTemplate
5
  from langchain_core.output_parsers import JsonOutputParser
6
+ from src.get_answer_gigachat import AnswerGigaChat
7
+ from src.service_by_name import get_service_by_name
8
+ from src.base_graph import BaseGraph
9
  import os
10
  from dotenv import load_dotenv
11
 
{services → src}/internet_access/__init__.py RENAMED
File without changes
{services → src}/internet_access/internet_access_cases.json RENAMED
File without changes