File size: 5,391 Bytes
1094f14
 
 
 
 
96f6b21
 
 
1094f14
 
 
 
 
b719109
1094f14
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
from pydantic import BaseModel, Field
from typing import Literal
import logging
from langchain.prompts import ChatPromptTemplate
from langchain_core.output_parsers import JsonOutputParser
from get_answer_gigachat import AnswerGigaChat
from service_by_name import get_service_by_name
from base_graph import BaseGraph
import os
from dotenv import load_dotenv

load_dotenv()

log_path = os.path.join("/tmp", "service.log")
if os.path.exists(log_path):
    os.remove(log_path)
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s',
    handlers=[
        logging.FileHandler(log_path)
    ]
)
logger = logging.getLogger(__name__)


class SupportCategory(BaseModel):
    """Структура для классификации вопроса техподдержки."""
    category: Literal["openvpn", "corporate_email", "internet_access", "другое"] = Field(
        description="Категория вопроса: openvpn, почта, wifi или другое"
    )
    confidence: float = Field(
        description="Уверенность модели в классификации (0-1)",
        ge=0,
        le=1
    )

llm = AnswerGigaChat()
parser = JsonOutputParser(pydantic_object=SupportCategory)

prompt = ChatPromptTemplate.from_template("""
Ты — вдумчивый и ответственный специалист технической поддержки. 
Под твоим руководством работают эксперты - работники технической поддержки, каждый из которых
разбирается в своем отдельном сервисе. Ты анализируешь поступающие вопросы и распределяешь их по экспертам. 
Тебе нужно понять, к какому сервису относится проблема пользователя и направить его к соответствующему эксперту.
Тебе не нужно уточнять у пользователя детали, чтобы точнее определить категорию задачи, 
ведь, если ты ошибешься, эксперт в ходе диалога это поймет
и перенаправит запрос на другого специалиста.

**Категории:**
- "openvpn" — если вопрос про VPN, подключение к корпоративной сети, сертификаты OpenVPN.
- "corporate_email" — вопрос отправляется к эксперту, который помогает с
    корпоративной почтой сотрудников компании, которая доступна по адресу mail-13.renlife.com
    и поддерживает работу через веб-интерфейс в браузере или через клиент Microsoft Outlook.
- "internet_access" — вопрос отправляется к эксперту, который помогает с вопросами про
    доступ в интернет, в том числе доступ к корпоративным ресурсам на корпоративной технике(пк, нб).
- "b2b" - ПО, обеспечивающее взаимодействие наших сотрудников с партнерами компании и наоборот, является web-формой общения с БД Borlas. В ПО реализована возможность заведения и просмотра уже созданных ДС.
- "crm" - ПО, которое позволяет управлять продажами и сотрудниками, проводить встречи и звонки. В системе предусмотрена возможность записи встреч и разговоров. Система работает в синергии с телефонией Naumen.
- "one_c" - 1С - Инструмент для автоматизации учета и управления бизнесом. Документооборот, бухгалтерия, кадровый учет, учет техники и оборудования.
- "borlas" - База данных клиентов, сотрудников, ДС.
- "print_and_scan" - Многофункциональное устройство (сокр. МФУ) — устройство, совмещающее в себе функции принтера, сканера, копировального аппарата, иногда также факса и терминала электронной почты, поточные сканеры
- "другое" — если вопрос не подходит ни под одну категорию.

Верни ответ в формате JSON с полями `category` и `confidence`.

**Вопрос пользователя:** {question}
""")

classification_chain = prompt | llm | parser


def get_graph_class(question):
    result = classification_chain.invoke({"question": question})
    service_name = result["category"]
    confidence = result["confidence"]
    logger.info(f"question: {question} goes to {service_name} with confidence {confidence}")
    service = BaseGraph(get_service_by_name(service_name))
    return service