kavlab
commited on
Commit
•
1e7f40c
1
Parent(s):
dc4c135
merged with github repo
Browse files- README.md +8 -4
- kuznetsov_av/test_api.py +1 -1
- mulyavin_aa/{PostmanLangDetect.png → screens/PostmanLangDetect.png} +0 -0
- mulyavin_aa/{PostmanTranslate.png → screens/PostmanTranslate.png} +0 -0
- mulyavin_aa/{audio_gen_image.png → screens/audio_gen_image.png} +0 -0
- requirements.txt +2 -1
- api.py → run_api.py +4 -4
- test/test_api.py +151 -0
- zvereva_ev/get_description_image.py +5 -5
README.md
CHANGED
@@ -9,7 +9,9 @@ app_file: run.py
|
|
9 |
pinned: false
|
10 |
---
|
11 |
|
12 |
-
|
|
|
|
|
13 |
|
14 |
Приложение разработано с использованием фреймворка [Streamlit](https://streamlit.io/).
|
15 |
Состоит из двух страниц и Главной страницы:
|
@@ -48,7 +50,7 @@ streamlit run run.py
|
|
48 |
### Генератор аудио
|
49 |
Необходимо ввести текст в текстовое поле и нажать кнопку "Генерировать!!!". В результате появится аудио запись на английском языке с описанием введенного текста.
|
50 |
|
51 |
-
![Результат работы моделей "Генератор аудио / Текст"](https://raw.githubusercontent.com/kavlab/urfu_iml_2023_1_3_hw2/main/mulyavin_aa/audio_gen_image.png)
|
52 |
![Результат работы моделей "Генератор аудио / Аудио"](https://raw.githubusercontent.com/kavlab/urfu_iml_2023_1_3_hw2/main/kuznetsov_av/text_to_speech_image.png)
|
53 |
|
54 |
### Описание изображения
|
@@ -65,7 +67,7 @@ streamlit run run.py
|
|
65 |
#### Пример вызова сервиса Определение языка текста
|
66 |
Вызвать url сервиса ```<host>/langdetector/detect``` методом POST
|
67 |
|
68 |
-
![img.png](https://raw.githubusercontent.com/kavlab/urfu_iml_2023_1_3_hw2/main/mulyavin_aa/PostmanLangDetect.png)
|
69 |
|
70 |
Передаваемые параметры:
|
71 |
```
|
@@ -89,7 +91,7 @@ streamlit run run.py
|
|
89 |
#### Пример вызова сервиса Перевод текста с языка Ru на En
|
90 |
Вызвать url сервиса ```<host>/translator/translate``` методом POST
|
91 |
|
92 |
-
![img.png](https://raw.githubusercontent.com/kavlab/urfu_iml_2023_1_3_hw2/main/mulyavin_aa/PostmanTranslate.png)
|
93 |
|
94 |
Передаваемые параметры:
|
95 |
```
|
@@ -137,3 +139,5 @@ streamlit run run.py
|
|
137 |
"url": "https://fikiwiki.com/uploads/posts/2022-02/1645000127_53-fikiwiki-com-p-kartinki-krasivie-babochki-narisovannie-55.png"
|
138 |
}
|
139 |
```
|
|
|
|
|
|
9 |
pinned: false
|
10 |
---
|
11 |
|
12 |
+
[![Tests](https://github.com/kavlab/urfu_iml_2023_1_3_hw2/actions/workflows/python-app.yml/badge.svg)](https://github.com/kavlab/urfu_iml_2023_1_3_hw2/actions/workflows/python-app.yml)
|
13 |
+
|
14 |
+
# Программная инженерия. Практические задания №2, №3, №4 и №5
|
15 |
|
16 |
Приложение разработано с использованием фреймворка [Streamlit](https://streamlit.io/).
|
17 |
Состоит из двух страниц и Главной страницы:
|
|
|
50 |
### Генератор аудио
|
51 |
Необходимо ввести текст в текстовое поле и нажать кнопку "Генерировать!!!". В результате появится аудио запись на английском языке с описанием введенного текста.
|
52 |
|
53 |
+
![Результат работы моделей "Генератор аудио / Текст"](https://raw.githubusercontent.com/kavlab/urfu_iml_2023_1_3_hw2/main/mulyavin_aa/screens/audio_gen_image.png)
|
54 |
![Результат работы моделей "Генератор аудио / Аудио"](https://raw.githubusercontent.com/kavlab/urfu_iml_2023_1_3_hw2/main/kuznetsov_av/text_to_speech_image.png)
|
55 |
|
56 |
### Описание изображения
|
|
|
67 |
#### Пример вызова сервиса Определение языка текста
|
68 |
Вызвать url сервиса ```<host>/langdetector/detect``` методом POST
|
69 |
|
70 |
+
![img.png](https://raw.githubusercontent.com/kavlab/urfu_iml_2023_1_3_hw2/main/mulyavin_aa/screens/PostmanLangDetect.png)
|
71 |
|
72 |
Передаваемые параметры:
|
73 |
```
|
|
|
91 |
#### Пример вызова сервиса Перевод текста с языка Ru на En
|
92 |
Вызвать url сервиса ```<host>/translator/translate``` методом POST
|
93 |
|
94 |
+
![img.png](https://raw.githubusercontent.com/kavlab/urfu_iml_2023_1_3_hw2/main/mulyavin_aa/screens/PostmanTranslate.png)
|
95 |
|
96 |
Передаваемые параметры:
|
97 |
```
|
|
|
139 |
"url": "https://fikiwiki.com/uploads/posts/2022-02/1645000127_53-fikiwiki-com-p-kartinki-krasivie-babochki-narisovannie-55.png"
|
140 |
}
|
141 |
```
|
142 |
+
|
143 |
+
Тестирует GitHub Actions
|
kuznetsov_av/test_api.py
CHANGED
@@ -1,5 +1,5 @@
|
|
1 |
from fastapi.testclient import TestClient
|
2 |
-
from kuznetsov_av.api import Request,
|
3 |
|
4 |
client = TestClient(app)
|
5 |
|
|
|
1 |
from fastapi.testclient import TestClient
|
2 |
+
from kuznetsov_av.api import Request, app
|
3 |
|
4 |
client = TestClient(app)
|
5 |
|
mulyavin_aa/{PostmanLangDetect.png → screens/PostmanLangDetect.png}
RENAMED
File without changes
|
mulyavin_aa/{PostmanTranslate.png → screens/PostmanTranslate.png}
RENAMED
File without changes
|
mulyavin_aa/{audio_gen_image.png → screens/audio_gen_image.png}
RENAMED
File without changes
|
requirements.txt
CHANGED
@@ -10,4 +10,5 @@ fastapi==0.104.1
|
|
10 |
uvicorn==0.24.0
|
11 |
httpx==0.25.2
|
12 |
pillow~=10.1.0
|
13 |
-
pydantic~=2.5.2
|
|
|
|
10 |
uvicorn==0.24.0
|
11 |
httpx==0.25.2
|
12 |
pillow~=10.1.0
|
13 |
+
pydantic~=2.5.2
|
14 |
+
requests~=2.31.0
|
api.py → run_api.py
RENAMED
@@ -1,3 +1,4 @@
|
|
|
|
1 |
import uvicorn
|
2 |
from fastapi import FastAPI
|
3 |
|
@@ -37,7 +38,7 @@ async def root():
|
|
37 |
},
|
38 |
{
|
39 |
"descr": "API для описания загруженного изображения",
|
40 |
-
"base_url": "/get_description_image"
|
41 |
}
|
42 |
]}
|
43 |
|
@@ -75,12 +76,11 @@ async def text_to_speech(entity: Request) -> Response:
|
|
75 |
@app.post("/get_description_image/predict/")
|
76 |
async def get_description_image_predict(item: develop_api_app.Url):
|
77 |
"""
|
78 |
-
Получение ссылки на изображение. Запись изображения
|
79 |
-
под названием 'image.png для получения его описания
|
80 |
"""
|
81 |
response = requests.get(item.url, stream=True)
|
82 |
# сохранение изображения для дальнейшей передачи в модель
|
83 |
-
with open("
|
84 |
f.write(response.content)
|
85 |
|
86 |
return get_description_image.get_description_image()
|
|
|
1 |
+
import os
|
2 |
import uvicorn
|
3 |
from fastapi import FastAPI
|
4 |
|
|
|
38 |
},
|
39 |
{
|
40 |
"descr": "API для описания загруженного изображения",
|
41 |
+
"base_url": "/get_description_image/predict/"
|
42 |
}
|
43 |
]}
|
44 |
|
|
|
76 |
@app.post("/get_description_image/predict/")
|
77 |
async def get_description_image_predict(item: develop_api_app.Url):
|
78 |
"""
|
79 |
+
Получение ссылки на изображение. Запись изображения под названием 'image_predict_test_image.png для получения его описания
|
|
|
80 |
"""
|
81 |
response = requests.get(item.url, stream=True)
|
82 |
# сохранение изображения для дальнейшей передачи в модель
|
83 |
+
with open(f"{os.path.dirname(__file__)}/zvereva_ev/image_predict_tmp.png", "wb") as f:
|
84 |
f.write(response.content)
|
85 |
|
86 |
return get_description_image.get_description_image()
|
test/test_api.py
ADDED
@@ -0,0 +1,151 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import kuznetsov_av
|
2 |
+
from fastapi.testclient import TestClient
|
3 |
+
from run_api import app
|
4 |
+
|
5 |
+
client = TestClient(app)
|
6 |
+
|
7 |
+
|
8 |
+
def test_get_description_image_predict() -> None:
|
9 |
+
"""
|
10 |
+
Тест API Описание загруженного изображения
|
11 |
+
"""
|
12 |
+
from zvereva_ev.develop_api_app import Url
|
13 |
+
|
14 |
+
response = client.post(
|
15 |
+
url="/get_description_image/predict/",
|
16 |
+
json=Url(url="https://fikiwiki.com/uploads/posts/2022-02/1645000127_53-"
|
17 |
+
"fikiwiki-com-p-kartinki-krasivie-babochki"
|
18 |
+
"-narisovannie-55.png"
|
19 |
+
).model_dump())
|
20 |
+
|
21 |
+
assert response.status_code == 200
|
22 |
+
assert response.text == '"Фото бабочки с оранжевыми крыльями и белыми точками"'
|
23 |
+
|
24 |
+
|
25 |
+
def test_langdetector_api_ru() -> None:
|
26 |
+
"""
|
27 |
+
Тест API определения языка текста RU (mulyavin_aa)
|
28 |
+
"""
|
29 |
+
import mulyavin_aa.model.langdetector
|
30 |
+
|
31 |
+
api_resp = client.post(
|
32 |
+
url="/langdetector/detect",
|
33 |
+
json=mulyavin_aa.model.langdetector.Request(
|
34 |
+
text='Доброго дня всем котам!').model_dump())
|
35 |
+
|
36 |
+
response = mulyavin_aa.model.langdetector.Response.model_validate_json(api_resp.text)
|
37 |
+
|
38 |
+
assert api_resp.status_code == 200
|
39 |
+
assert len(response.langs) > 0
|
40 |
+
assert response.langs[0].label == 'ru'
|
41 |
+
|
42 |
+
|
43 |
+
def test_langdetector_api_en() -> None:
|
44 |
+
"""
|
45 |
+
Тест API определения языка текста EN (mulyavin_aa)
|
46 |
+
"""
|
47 |
+
import mulyavin_aa.model.langdetector
|
48 |
+
|
49 |
+
api_resp = client.post(
|
50 |
+
url="/langdetector/detect",
|
51 |
+
json=mulyavin_aa.model.langdetector.Request(
|
52 |
+
text='So I checked functions in the class model').model_dump())
|
53 |
+
|
54 |
+
response = mulyavin_aa.model.langdetector.Response.model_validate_json(api_resp.text)
|
55 |
+
|
56 |
+
assert api_resp.status_code == 200
|
57 |
+
assert len(response.langs) > 0
|
58 |
+
assert response.langs[0].label == 'en'
|
59 |
+
|
60 |
+
|
61 |
+
def test_langdetector_api_err() -> None:
|
62 |
+
"""
|
63 |
+
Тест API определения языка текста не Ru и En (mulyavin_aa)
|
64 |
+
Модель не ограничена только Ru и En
|
65 |
+
"""
|
66 |
+
import mulyavin_aa.model.langdetector
|
67 |
+
|
68 |
+
api_resp = client.post(
|
69 |
+
url="/langdetector/detect",
|
70 |
+
json=mulyavin_aa.model.langdetector.Request(
|
71 |
+
text='').model_dump())
|
72 |
+
|
73 |
+
response = mulyavin_aa.model.langdetector.Response.model_validate_json(api_resp.text)
|
74 |
+
|
75 |
+
assert api_resp.status_code == 200
|
76 |
+
assert len(response.langs) > 0
|
77 |
+
assert response.langs[0].label != 'en'
|
78 |
+
assert response.langs[0].label != 'ru'
|
79 |
+
|
80 |
+
|
81 |
+
def test_translator_ru_to_en() -> None:
|
82 |
+
"""
|
83 |
+
Тест API Перевод текста с языка Ru на En (mulyavin_aa)
|
84 |
+
"""
|
85 |
+
import mulyavin_aa.model.translator
|
86 |
+
|
87 |
+
api_resp = client.post(
|
88 |
+
url="/translator/translate",
|
89 |
+
json=mulyavin_aa.model.translator.Request(
|
90 |
+
text='Доброго деня всем котам!').model_dump())
|
91 |
+
|
92 |
+
response = mulyavin_aa.model.translator.Response.model_validate_json(api_resp.text)
|
93 |
+
|
94 |
+
assert api_resp.status_code == 200
|
95 |
+
assert len(response.text) > 0
|
96 |
+
assert response.text == 'Good day to all cats!'
|
97 |
+
|
98 |
+
|
99 |
+
def test_translator_en_to_en() -> None:
|
100 |
+
"""
|
101 |
+
Тест API Перевод текста с языка En на En (mulyavin_aa)
|
102 |
+
"""
|
103 |
+
import mulyavin_aa.model.translator
|
104 |
+
|
105 |
+
api_resp = client.post(
|
106 |
+
url="/translator/translate",
|
107 |
+
json=mulyavin_aa.model.translator.Request(
|
108 |
+
text='Good day to all cats!').model_dump())
|
109 |
+
|
110 |
+
response = mulyavin_aa.model.translator.Response.model_validate_json(api_resp.text)
|
111 |
+
|
112 |
+
assert api_resp.status_code == 200
|
113 |
+
assert len(response.text) > 0
|
114 |
+
assert response.text == 'Good day to all cats!'
|
115 |
+
|
116 |
+
|
117 |
+
def test_text_to_speech_ok():
|
118 |
+
"""
|
119 |
+
Тест API преобразования текста в речь
|
120 |
+
"""
|
121 |
+
response = client.post(
|
122 |
+
url='/text-to-speech/convert/',
|
123 |
+
json=kuznetsov_av.api.Request(text='Test').model_dump()
|
124 |
+
)
|
125 |
+
|
126 |
+
assert response.status_code == 200
|
127 |
+
assert response.json().get('audio') is not None
|
128 |
+
assert type(response.json().get('audio')) == str
|
129 |
+
assert len(response.json().get('audio')) > 0
|
130 |
+
assert response.json().get('sampling_rate') is not None
|
131 |
+
assert type(response.json().get('sampling_rate')) == int
|
132 |
+
|
133 |
+
|
134 |
+
def test_text_to_speech_error422():
|
135 |
+
"""
|
136 |
+
Тест API преобразования текста в речь
|
137 |
+
"""
|
138 |
+
response = client.post(
|
139 |
+
url='/text-to-speech/convert/',
|
140 |
+
json=''
|
141 |
+
)
|
142 |
+
|
143 |
+
assert response.status_code == 422
|
144 |
+
|
145 |
+
|
146 |
+
def test_root():
|
147 |
+
response = client.get('/')
|
148 |
+
|
149 |
+
assert response.status_code == 200
|
150 |
+
assert response.json().get('message') is not None
|
151 |
+
assert len(response.json().get('message')) > 0
|
zvereva_ev/get_description_image.py
CHANGED
@@ -20,7 +20,7 @@ def load_image():
|
|
20 |
st.image(image_data)
|
21 |
image_data_open = Image.open(io.BytesIO(image_data))
|
22 |
# Сохранение изображения из буффера
|
23 |
-
image_data_open.save("
|
24 |
return image_data_open
|
25 |
else:
|
26 |
return None
|
@@ -39,7 +39,7 @@ def get_description_image():
|
|
39 |
"""
|
40 |
processor, model = load_models()
|
41 |
|
42 |
-
raw_image = Image.open("
|
43 |
|
44 |
text = "a photography of"
|
45 |
inputs = processor(raw_image, text, return_tensors="pt")
|
@@ -53,7 +53,7 @@ def get_description_image():
|
|
53 |
|
54 |
|
55 |
# Получение полного пути к сохраненному изображению из буффера
|
56 |
-
file_path = "
|
57 |
absolute_path = os.path.abspath(file_path)
|
58 |
|
59 |
|
@@ -71,7 +71,7 @@ def run_():
|
|
71 |
st.warning("Загрузите изображение, чтобы получить описание", icon="🚀")
|
72 |
else:
|
73 |
exit()
|
74 |
-
if "
|
75 |
-
os.remove("
|
76 |
except FileNotFoundError:
|
77 |
return "Изображение не загружено"
|
|
|
20 |
st.image(image_data)
|
21 |
image_data_open = Image.open(io.BytesIO(image_data))
|
22 |
# Сохранение изображения из буффера
|
23 |
+
image_data_open.save(f"{os.path.dirname(__file__)}/image_predict_tmp.png")
|
24 |
return image_data_open
|
25 |
else:
|
26 |
return None
|
|
|
39 |
"""
|
40 |
processor, model = load_models()
|
41 |
|
42 |
+
raw_image = Image.open(f"{os.path.dirname(__file__)}/image_predict_tmp.png")
|
43 |
|
44 |
text = "a photography of"
|
45 |
inputs = processor(raw_image, text, return_tensors="pt")
|
|
|
53 |
|
54 |
|
55 |
# Получение полного пути к сохраненному изображению из буффера
|
56 |
+
file_path = f"{os.path.dirname(__file__)}/image_predict_tmp.png"
|
57 |
absolute_path = os.path.abspath(file_path)
|
58 |
|
59 |
|
|
|
71 |
st.warning("Загрузите изображение, чтобы получить описание", icon="🚀")
|
72 |
else:
|
73 |
exit()
|
74 |
+
if f"{os.path.dirname(__file__)}/image_predict_tmp.png" in absolute_path:
|
75 |
+
os.remove(f"{os.path.dirname(__file__)}/image_predict_tmp.png")
|
76 |
except FileNotFoundError:
|
77 |
return "Изображение не загружено"
|