File size: 4,319 Bytes
60ebe5d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b5e749a
 
 
 
 
 
 
 
d43abcf
60ebe5d
 
 
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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# type: ignore
from typing import List, Tuple

import gradio as gr
import pandas as pd
import torch
from langchain_community.llms import CTransformers
from langchain_core.output_parsers import PydanticOutputParser
from langchain_core.prompts import PromptTemplate
from langchain_core.pydantic_v1 import BaseModel, Field
from loguru import logger
from transformers import pipeline

logger.add("logs/file_{time}.log")


# asr model
device = "cuda:0" if torch.cuda.is_available() else "cpu"
logger.info(f"Device: {device}")
pipe = pipeline(
    "automatic-speech-recognition",
    model="openai/whisper-medium",
    chunk_length_s=30,
    # device=device,
    generate_kwargs={"language": "russian"},
)


# qa model
class Result(BaseModel):
    """Извлечь вопрос и ответ из аудио записи колл-центра"""

    question: str = Field(..., description="Вопрос клиента")
    answer: str = Field(..., description="Ответ оператора")


class Results(BaseModel):
    results: List[Result] = Field(..., description="Пары вопрос-ответ")


config = {
    "max_new_tokens": 1000,
    "context_length": 3000,
    "temperature": 0,
    # "gpu_layers": 50,
}
llm = CTransformers(
    model="TheBloke/saiga_mistral_7b-GGUF",
    config=config,
)

# accelerator = Accelerator()
# llm, config = accelerator.prepare(llm, config)


def asr(audio_file) -> str:
    transcribed_text = pipe(audio_file, batch_size=16)
    logger.info(f"Transcribed text: {transcribed_text}")

    return transcribed_text["text"]
    # return "Здравствуйте, меня зовут Александр, чем могу помочь? До скольки вы работаете? До 20:00. Спасибо, до свидания!"


def qa(transcribed_text: str) -> Tuple[str, str]:
    parser = PydanticOutputParser(pydantic_object=Results)
    prompt = PromptTemplate(
        template="На основе транскрипции звонка из колл-центра определите пары вопросов и ответов, выделив конкретные вопросы, которые задал клиент, и ответы, которые предоставил оператор.\n{format_instructions}\nТекст аудио записи: {transcribed_text}\n",
        # template="Какой вопрос задал клиент? Какой ответ дал оператор?\n{format_instructions}\nТекст аудио записи: {transcribed_text}\n",
        input_variables=["transcribed_text"],
        partial_variables={"format_instructions": parser.get_format_instructions()},
    )
    prompt_and_model = prompt | llm

    output = prompt_and_model.invoke({"transcribed_text": transcribed_text})
    logger.info(f"Output: {output}")

    results = parser.invoke(output)
    logger.info(f"Result: {results}")
    logger.info(f"Dict: {results.dict()}")

    results = (
        pd.DataFrame(results.dict())
        .results.apply(pd.Series)
        .rename({"question": "Вопрос", "answer": "Ответ"}, axis=1)
    )

    return transcribed_text, results


@logger.catch
def inference(audio_file):
    transcribed_text = asr(audio_file)
    return qa(transcribed_text)


demo = gr.Interface(
    fn=inference,
    inputs=[
        gr.Audio(
            label="Аудио запись для обработки",
            sources="upload",
            type="filepath",
        )
    ],
    outputs=[
        gr.components.Textbox(label="Транскрибированный текст"),
        gr.DataFrame(headers=["Вопрос", "Ответ"], label="Вопросы и ответы"),
    ],
    submit_btn="Обработать",
    clear_btn="Очистить",
    allow_flagging="never",
    title="Обработчик аудиозаписей колл-центра",
    description="Распознавание речи и определение вопроса клиента и ответа оператора.",
    css="footer {visibility: hidden}",
    examples=[
        "samples/out_olga2.mp3",
        "samples/all_kfc.mp3",
        "samples/all_nastya.mp3",
        "samples/all_victor.mp3",
        "samples/in_elena.mp3",
        "samples/in_natalia.mp3",
    ],
    cache_examples=False,
)

demo.launch()