-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrun.py
151 lines (127 loc) · 7.7 KB
/
run.py
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
import gradio as gr
import whisper
import openai
from dotenv import load_dotenv
import os
import logging
# Настройка логирования
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
# Загрузка API ключа из .env файла
load_dotenv()
openai.api_key = os.getenv("OPENAI_API_KEY")
starting_prompt = """Вы — ассистент.
Вы можете обсуждать с пользователем или выполнять задачи, связанные с письмами. Письма требуют тему, адресата и тело письма.
Вы будете получать инструкции, начинающиеся с [Instruction], или ввод пользователя, начинающийся с [User]. Следуйте инструкциям.
"""
prompts = {
'START': '[Instruction] Напишите WRITE_EMAIL, если пользователь хочет написать письмо, "QUESTION", если у пользователя есть конкретный вопрос, "OTHER" в любом другом случае. Напишите только одно слово.',
'QUESTION': '[Instruction] Если вы можете ответить на вопрос, напишите "ANSWER", если вам нужно больше информации, напишите "MORE", если вы не можете ответить, напишите "OTHER". Напишите только одно слово.',
'ANSWER': '[Instruction] Ответьте на вопрос пользователя.',
'MORE': '[Instruction] Попросите пользователя предоставить больше информации в соответствии с предыдущими инструкциями.',
'OTHER': '[Instruction] Дайте вежливый ответ или приветствие, если пользователь ведет вежливый разговор. В противном случае сообщите, что вы не можете ответить на вопрос или выполнить действие.',
'WRITE_EMAIL': '[Instruction] Если отсутствует тема, адресат или тело письма, ответьте "MORE". В противном случае, если у вас есть вся информация, ответьте "ACTION_WRITE_EMAIL | subject:subject, recipient:recipient, message:message".',
'ACTION_WRITE_EMAIL': '[Instruction] Письмо отправлено. Сообщите пользователю, что действие выполнено.'
}
actions = ['ACTION_WRITE_EMAIL']
class Discussion:
"""
Класс, представляющий обсуждение с голосовым помощником.
Атрибуты:
state (str): Текущее состояние обсуждения.
messages_history (list): История сообщений.
stt_model: Модель распознавания речи Whisper.
Методы:
generate_answer: Генерирует ответ на основе сообщений.
reset: Сбрасывает обсуждение в начальное состояние.
do_action: Выполняет указанное действие.
transcribe: Распознает текст из аудиофайла.
discuss_from_audio: Начинает обсуждение на основе аудиофайла.
discuss: Продолжает обсуждение на основе пользовательского ввода.
"""
def __init__(self, state='START', messages_history=None) -> None:
self.state = state
self.messages_history = messages_history or [{'role': 'user', 'content': starting_prompt}]
self.stt_model = whisper.load_model("base")
def generate_answer(self, messages):
try:
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=messages
)
answer = response['choices'][0]['message']['content']
usage = response['usage'] # Информация об использовании токенов
print(f"\nОтвет: {answer}")
print(f"Использование токенов: "
f"Промпт: {usage['prompt_tokens']}, "
f"Ответ: {usage['completion_tokens']}, "
f"Всего: {usage['total_tokens']}\n")
return answer
except openai.error.OpenAIError as e:
logging.error(f"Ошибка OpenAI: {e}")
return "Извините, произошла ошибка при обработке вашего запроса."
def reset(self, start_state='START'):
self.messages_history = [{'role': 'user', 'content': starting_prompt}]
self.state = start_state
self.previous_state = None
def reset_to_previous_state(self):
self.state = self.previous_state
self.previous_state = None
def to_state(self, state):
self.previous_state = self.state
self.state = state
def do_action(self, action):
"""
Выполняет указанное действие.
Args:
action (str): Действие для выполнения.
"""
print(f'Выполняется действие: {action}')
# Здесь можно добавить реальную логику для отправки письма или других действий.
pass
def transcribe(self, file):
transcription = self.stt_model.transcribe(file)
return transcription['text']
def discuss_from_audio(self, file):
if file:
# Распознаем аудио и запускаем обсуждение с текстом
return self.discuss(f'[User] {self.transcribe(file)}')
# Если файл отсутствует
return ''
def discuss(self, input=None):
if input is not None:
self.messages_history.append({"role": "user", "content": input})
# Генерация ответа
completion = self.generate_answer(
self.messages_history + [{"role": "user", "content": prompts[self.state]}]
)
# Проверка, является ли результат действием
if completion.split("|")[0].strip() in actions:
action = completion.split("|")[0].strip()
self.to_state(action)
self.do_action(completion)
# Продолжаем обсуждение
return self.discuss()
# Проверка, является ли результат новым состоянием
elif completion in prompts:
self.to_state(completion)
# Продолжаем обсуждение
return self.discuss()
# Ответ для пользователя
else:
self.messages_history.append({"role": "assistant", "content": completion})
if self.state != 'MORE':
# Возвращаемся в начальное состояние
self.reset()
else:
# Возвращаемся к предыдущему состоянию
self.reset_to_previous_state()
return completion
if __name__ == '__main__':
discussion = Discussion()
gr.Interface(
theme=gr.themes.Soft(),
fn=discussion.discuss_from_audio,
live=True,
inputs=gr.Audio(type="filepath"), # Убрали аргумент `source`
outputs="text"
).launch()