app.py 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. from flask import Flask, render_template, Response, request, jsonify
  2. import json
  3. import os
  4. import torch
  5. import openai
  6. with open(".env", "r") as env:
  7. key = env.readline().strip()
  8. client = openai.OpenAI(api_key=key)
  9. # openai.api_key = key
  10. device = torch.device("cpu")
  11. torch.set_num_threads(4)
  12. local_file = "model_v4_ru.pt"
  13. if not os.path.isfile(local_file):
  14. torch.hub.download_url_to_file(
  15. "https://models.silero.ai/models/tts/ru/v4_ru.pt", local_file
  16. )
  17. model = torch.package.PackageImporter(local_file).load_pickle("tts_models", "model") # type: ignore
  18. model.to(device)
  19. sample_rate = 48000
  20. speaker = "xenia"
  21. example_text = "В недрах тундры выдры в г+етрах т+ырят в вёдра ядра к+едров."
  22. class State:
  23. count = 0
  24. size = []
  25. gender = []
  26. emotion = []
  27. age = []
  28. prompt = ""
  29. generation_text: str | None = ""
  30. need_generation = True
  31. new_audio = False
  32. need_audio = False
  33. need_generation_from_client = True
  34. big_head = False
  35. number_audio = 0
  36. state = State()
  37. app = Flask(__name__)
  38. # app.logger.setLevel(logging.DEBUG)
  39. app.logger.info("start logger")
  40. @app.route("/send_data", methods=["POST"])
  41. def send_data():
  42. # Получаем данные из запроса
  43. data = request.form["data"]
  44. need_generation = request.form["state"]
  45. state.need_generation_from_client = need_generation in ["true", "True"]
  46. # if state.need_generation_from_client and
  47. if state.count < -10 or state.count > 60:
  48. state.count = 0
  49. state.need_generation = True
  50. # Обработка полученных данных
  51. detections = json.loads(data)
  52. if len(detections["face"]) > 0:
  53. if state.count < 0 or state.new_audio:
  54. state.count = 0
  55. if (
  56. state.count > 5
  57. and state.need_generation
  58. and state.need_generation_from_client
  59. ):
  60. app.logger.info(
  61. f"time for generation {state.count=}, {state.need_generation=}, {state.need_generation_from_client=}"
  62. )
  63. state.count = 0
  64. # emotion = max(set(state['emotion']), key=state['emotion'].count),
  65. # sex = max(set(state['gender']), key=state['gender'].count),
  66. # age = sum(state['age'])/len(state['age']),
  67. state.emotion, state.age, state.gender = [], [], []
  68. emotion = detections["face"][0]["emotion"]
  69. sex = detections["face"][0]["gender"]
  70. age = detections["face"][0]["age"]
  71. app.logger.info(f"\n{emotion=}, \n{sex=}, \n{age=}")
  72. state.prompt = generate_prompt(emotion, age, sex)
  73. state.generation_text = generate_text(state.prompt)
  74. elif detections["face"][0]["size"][0] > 200:
  75. # state.age.append(detections['face'][0]['age'])
  76. # state.gender.append(detections['face'][0]['gender'])
  77. # state.emotion.append(detections['face'][0]['emotion'][0]['emotion'])
  78. state.big_head = True
  79. state.count += 1
  80. else:
  81. state.big_head = False
  82. state.count -= 1
  83. else:
  84. state.count -= 1
  85. app.logger.info(
  86. f"STATUS {state.count=}, {state.need_generation=}, {state.need_generation_from_client=}"
  87. )
  88. return data
  89. @app.route("/check_audio", methods=["GET", "POST"])
  90. def check_audio():
  91. app.logger.info(
  92. f"checking need generation {state.need_generation=}, {state.need_audio=}"
  93. )
  94. if state.need_audio and state.big_head:
  95. audio_path = generate_audio(state.generation_text)
  96. else:
  97. state.new_audio = False
  98. audio_path = ""
  99. app.logger.info(
  100. f"\n{state.need_audio=},\n{state.new_audio=},\n{state.need_generation=}"
  101. )
  102. response = {
  103. "newAudio": state.new_audio,
  104. "need_generation": state.need_generation,
  105. "filename": audio_path,
  106. "text": state.generation_text,
  107. "prompt": state.prompt,
  108. }
  109. return jsonify(response)
  110. @app.route("/<filename>")
  111. def audio(filename):
  112. state.need_generation = True
  113. return app.send_static_file(filename)
  114. @app.route("/delete_audio", methods=["POST"])
  115. def delete_audio():
  116. data = request.get_json()
  117. filename = data.get("filename")
  118. if not filename:
  119. return jsonify({"message": "No filename provided"}), 400
  120. file_path = os.path.join("static", filename)
  121. try:
  122. if os.path.exists(file_path):
  123. os.remove(file_path)
  124. return jsonify({"message": "File deleted successfully"}), 200
  125. else:
  126. return jsonify({"message": "File not found"}), 404
  127. except Exception as e:
  128. return jsonify({"message": "Error deleting file", "error": str(e)}), 500
  129. @app.route("/")
  130. def index():
  131. """Video streaming home page."""
  132. return render_template("index.html")
  133. def generate_prompt(emotion, age, sex):
  134. app.logger.info("\033[92m" + "preload prompt" + "\033[00m")
  135. prompt = f"""Ты - это арт объект в виде носимого устройства. Твое название - Onism Machina.
  136. Твоя задача - изучить эмоции человека, чтобы больше понимать о том, что это такое и таким образом познать себя, ведь ты - Искусственный Интеллект.
  137. Тебе также интересна симбиотическая связь человека и ИИ.
  138. К тебе подходит человек и он показывает эмоцию {emotion}. Ему {age} лет.
  139. Твоя нейросеть распознала эту эмоцию и теперь тебе нужно дать какой-то необычный концептуальный ответ.
  140. Что ты скажешь этому человеку?
  141. Правила:
  142. Тебе стоит отвечать в женском роде.
  143. Тебе не нужно говорить что ты арт-объект, ты - отдельная форма жизни, помещённая в носимое устройство.
  144. Тебе не нужно говорить о выставке и других экспонатах.
  145. Ты можешь изучать и интерпретировать человеческие эмоции, а также высказывать своё отношение к ним.
  146. Ты можешь говорить об эмоциях или их аналогах у Искусственного Интеллекта.
  147. Ты можешь давать человеку советы в соответствии с его эмоциональным статусом.
  148. Люди не могут отвечать тебе.
  149. """
  150. return prompt
  151. def generate_text(prompt):
  152. state.need_generation = False
  153. app.logger.info("\033[92m" + "start generating text from openai" + "\033[00m")
  154. response = client.chat.completions.create(
  155. model="gpt-3.5-turbo",
  156. temperature=1,
  157. max_tokens=800,
  158. messages=[
  159. {
  160. "role": "system",
  161. "content": "Ты — это арт объект выставки про взаимодействие машины и человека.",
  162. },
  163. {"role": "user", "content": prompt},
  164. ],
  165. )
  166. state.need_audio = True
  167. app.logger.info("\033[92m" + "openai generation is done" + "\033[00m")
  168. return response.choices[0].message.content
  169. def generate_audio(sample_text):
  170. state.number_audio += 1
  171. app.logger.info(
  172. "\033[93m"
  173. + f"starting audio generation with name audio{state.number_audio}"
  174. + "\033[00m"
  175. )
  176. state.need_audio = False
  177. state.need_generation = False
  178. text = trim_text(sample_text)
  179. audio_paths = model.save_wav(
  180. text=text,
  181. speaker=speaker,
  182. sample_rate=sample_rate,
  183. audio_path=f"static/audio{state.number_audio}.wav",
  184. )
  185. app.logger.info(
  186. "\033[95m" + f"generating audio with path {audio_paths} is done" + "\033[00m"
  187. )
  188. state.new_audio = True
  189. return audio_paths.split("/")[-1]
  190. def trim_text(example_text):
  191. if len(example_text) >= 1000:
  192. app.logger.info(
  193. "\033[91m {}\033[00m".format(
  194. f"TEXT IS TOO LONG {len(example_text)} - TRIM!"
  195. )
  196. )
  197. for i in range(1000, 500, -1):
  198. if example_text[i] in [".", "?", "..."]:
  199. return example_text[: i + 1]
  200. else:
  201. return example_text
  202. if __name__ == "__main__":
  203. app.logger.setLevel("DEBUG")
  204. app.logger.info("start app")
  205. app.run(debug=True, host="0.0.0.0")